From 88c4b4222aa59200fed9d652a6dc020336e0e750 Mon Sep 17 00:00:00 2001 From: Aanchal Malhotra Date: Wed, 9 Aug 2023 16:43:04 -0400 Subject: [PATCH 01/17] Add files via upload --- XLS-30/README.md | 1255 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1255 insertions(+) create mode 100644 XLS-30/README.md diff --git a/XLS-30/README.md b/XLS-30/README.md new file mode 100644 index 00000000..2661e038 --- /dev/null +++ b/XLS-30/README.md @@ -0,0 +1,1255 @@ +
    
+  Title:        Automated Market Maker on XRPL
+  Revision:     4 (2023-08-08)
+
+
Author: Aanchal Malhotra + David J. Schwartz + Affiliation: Ripple +
+# Automated Market Maker on XRP Ledger + +### Abstract +The XRPL decentralized exchange (DeX) currently provides liquidity exclusively by manual market making and order books. This proposal adds non-custodial automated market maker (AMM) as a native feature to the XRPL DeX in a way that provides increased returns to those who provide liquidity for the AMM and minimizes the risk of losses due to volatility. + +We propose a unique mechanism where the AMM instance continuously auctions off trading advantages to arbitrageurs, charging them and giving these earnings to its liquidity providers. This allows liquidity providers to take a large share of the profits that would normally be taken by arbitrageurs. + +The AMM instance charges a spread on the trades that change the ratio of tokens in the instance's pools. This trading fee is added to the AMM instance's capital pool, thus adding to the liquidity providers' returns. + +The AMM instances also provide governance rights to the largest share holders of the AMM instance. This allows them to vote on the trading fee the instance charges. + +XRPL's AMM based DeX interacts with XRPL's limit order book (LOB) based DeX so that users of AMM pools have access to all order flow and liquidity on LOB DeX, and vice versa. The payment and order placement transactors automatically determine whether swapping within a liquidity pool or through the order book will provide the best price for the user and execute accordingly. Pathfinding considers paths with both order books and AMMs in various combinations to improve the overall exchange rate. + +### 1. Introduction +AMMs are agents that pool liquidity and make it available to traders according to a predetermined algorithm. This is a proposal for geometric mean market maker (GM3) based DeX as a native XRPL feature. GM3 algorithmically discovers a fair exchange value, stabilized by arbitrage, to automatically produce liquidity. On XRPL, this would provide liquidity pools between XRP and issued assets as well as between any two issued assets. Arbitrageurs play a significant role in keeping the AMM DeX in a stable state with respect to external markets. + +Several things that contribute to the costs that trading imposes on AMM pools are naturally much less significant on XRPL: + +- **Low transaction fee:** An arbitrageur only submits a transaction when the expected profit from the transaction exceeds the transaction fee. XRPL’s transaction fees are much lower than those on most DeFi chains. This benefits the AMM instance pools by narrowing the time windows in which the instance suffers decreased trading volume due to its spot-market price being off due to volatility or asymmetric trading. + +- **Fast finality:** Arbitrageurs take risk (for which they must be compensated at the instance pool’s expense) due to the block times. Prices may change while their transaction is in flux. XRPL has faster block times than many of the fastest competing major blockchains. + +- **Canonical transaction ordering:** Transactions on XRPL are canonically ordered. Other blockchains have block producers, miners, or stakers who try to extract value from arbitrage transactions by delaying, reordering, front-running, or selectively including them to extract more value from the pool and the arbitrageurs. XRPL doesn’t have this. + +AMMs are more effective and lucrative when transactions execute quickly, cheaply, and fairly. This means that XRPL AMM could provide more liquidity at lower prices, yet still provide a compelling return. + +#### 1.1. Terminology + +1. **Conservation Function**: We propose a weighted geometric mean market maker (GM3) for AMM price discovery: + +$$C = \Gamma_{A}^{W_{A}} * \Gamma_{B}^{W_{B}} \tag{I}$$ + +where, + +- $\Gamma_{A}$: Current balance of token $A$ in the AMM instance pool +- $\Gamma_{B}$: Current balance of token $B$ in the AMM instance pool +- $W_{A}$: Normalized weight of token $A$ in the AMM instance pool +- $W_{B}$: Normalized weight of token $B$ in the AMM instance pool + +In this version of the proposal, pools must be of equal value. The implicit normalized weights are $W_{A} = W_{B} = 0.5$. + +2. **Liquidity Providers**: Liquidity providers (LPs) are the traders who add liquidity to the AMM instance's pools, thus earning shares of the pools in the form of `LPTokens`. + +3. **LPTokens**: LP tokens represent the liquidity providers' shares of the AMM instance's pools. `LPTokens` are [tokens](https://xrpl.org/tokens.html) on XRPL. Each `LPToken` represents a proportional share of each pool of the AMM instance. The AMM instance account _issues_ the `LPTokens` to LPs upon liquidity provision. `LPTokens` are _balanced_ in the LPs trustline upon liquidity removal. + +4. **Spot-Price**: Spot-price (SP) is the weighted ratio of the instance's pool balances. $SP_{A}^{B}$ is the spot-price of asset $A$ relative to asset $B$. $TFee$ is the trading fee paid by the trader for trades executed against the AMM instance. + + + + +$$SP_{A}^{B} = \frac{\frac{\Gamma_B}{W_B}}{\frac{\Gamma_A}{W_A}} * \frac{1}{\left(1-TFee\right)} \tag{II}$$ + +5. **Effective-Price**: The effective price (EP) of a trade is defined as the ratio of the tokens the trader sold or swapped in (Token $B$) and the token they got in return or swapped out (Token $A$). + +$$EP_{A}^{B} = \frac{\Delta_B}{\Delta_A} \tag{III}$$ + + + +6. **Slippage**: Slippage is defined as the percentage change in the effective price of a trade relative to the pre-swap spot-price. + +#### 1.2. Overview of XRPL AMM features +**AMM Instance Representation** + - We propose the existing [**`AccountRoot`**](https://xrpl.org/accountroot.html) ledger entry and a new ledger entry **`AMM`** to represent an AMM instance with two asset pools. New transaction type **`AMMCreate`** is used to create **`AccountRoot`** and the corresponding **`AMM`** ledger entries. In this version we propose to allow for the creation of only one AMM instance per unique asset pair. + +**Trading on AMM Instance** + - To enable adding and removing liquidity to and from the two pools of the AMM instance, we introduce two new transaction types **`AMMDeposit`** and **`AMMWithdraw`** respectively. The proposal allows for both _equal-asset_ as well as _single-sided_ deposits and withdrawals. Adding liquidity to an AMM instance yields pool shares called **`LPTokens`** that are issued by the AMM instance represented as XRPL [tokens](https://xrpl.org/tokens.html#tokens). **`LPTokens`** can be bought, sold and can be used to make payments exactly as other issued assets/tokens on the ledger. + + - To enable exchanging one pool asset of the AMM instance for the other - a swap - we propose the existing [**`Payment`**](https://xrpl.org/payment.html) transaction. + +**Votable Trading Fee** + - The AMM instance charges a trading fee on the portion of the trade that changes the ratio of tokens in the AMM instance. This fee is added to the AMM instance's pools and is distributed proportionally to the **`LPToken`** holders upon redemption of **`LPTokens`**. +High trading fee may deter user participation, thus reducing the trading volume and consequently LPs revenue. On the other hand, low trading fee naturally means lower revenue for LPs. Instead of hardcoding the trading fee in the protocol, we propose it be a votable parameter for the **`LPToken`** holders. The assumption is that LPs being the significant stakeholders in an AMM instance are best positioned to collectively make this decision in a balanced way. + +**Two-way Interoperable AMM and LOB-based DeXs** + - XRPL's AMM-based and the existing LOB-based DeXs are two-way interoperable, i.e. the interleaved execution of the AMM trades with the existing order book based DeX on XRPL. The key to this integration is transparent injection of the AMM offer into the liquidity stream, which is fed into the payment execution engine. This ensures aggregated liquidity across different DeXs and better exchange rate for the traders. + +**Novel Feature: Continuous Auction Mechanism** + - Problem: Due to volatility or asymmetric trading, when relative price of assets in AMM pools goes out-of-sync with that of external markets, AMM does not adjust the prices automatically due to lack of external market information (price-feed) natively. As a result, arbitrageurs intervene, but they have to: + - Wait until the profit from the arbitrage transaction (and thus the pool’s expected loss) exceeds the trading fees + - Race/Compete against others, thus reducing their success probability + + - Implications: Liquidity Providers lose because: + - During the __wait window__, there is a decreased trading volume (and thus decreased revenue) for the pool + - Arbitrageurs make profits from arbitrage transaction at pool's (LPs’) expense + + - Our Approach: Create a mechanism that makes it: + - Easy (higher success probability) for arbitrageurs by eliminating the race condition, AND + - Profitable for liquidity providers by further narrowing the window of decreased trading volume for the pool and sharing the profits from arbitrage transaction + + - Our Innovative Solution: To achieve the above mentioned, we introduce a mechanism for the AMM instance to continuously auction-off trading advantages for a 24-hour slot at zero trading fee! Anyone can bid for the auction slot with the units of **`LPtokens`**. The slot-holder can send the arbitrage transaction **immediately** without the need to wait for their profits to exceed the trading fee, thus eliminating the race condition for them. This also reduces the **time window** for which the pool suffers decreased trading volume. Additionally, part of proceeds (**`LPTokens`**) from the auction are deleted/burnt that effectively increases LP token holders' ownership in the pool proportionally. Since it's a continuous auction mechanism, if someone outbids an auction slot-holder, part of proceeds from the auction are refunded to the previous slot-holder (computed pro-rata). For details refer Section 5. + +As slot holder will have significant advantages for arbitrage, it’s expected that arbitrageurs will bid up the price of the auction slot to nearly the value they extract through arbitrage. + + - Expected Results + - Eliminates wait time & race condition for auction slot holder (arbitrageur) + - Narrows time windows in which the pool suffers decreased trading volume + - Liquidity providers additionally reap a share of profits that would otherwise go JUST to arbitrageurs + +## 2. Creating AMM instance on XRPL + +### 2.1. On-Ledger Objects + +We propose the existing **`AccountRoot`** object together with a new ledger object **`AMM`** to represent an AMM instance. Currently, the **`AccountRoot`** object type describes a single account, its settings, and XRP balance on the XRP ledger. The **`AccountRoot`** and the **`AMM`** objects that represent an AMM instance can be created using the new **`AMMCreate`** transaction. XRP balance of the AMM instance pools is always tracked via the existing `Balance` field of the **`AccountRoot`** object. The issued asset balances of the AMM instance pools and **`LPTokens`** are automatically tracked via trustlines. The AMM can be traded against using the new **`AMMDeposit`** and **`AMMWithdraw`** and the existing **`Payment`** transactions. Additionally, the AMM instance in "empty" state can be deleted using the `AMMDelete` transaction. + +Note that in this version, only equal-weighted two asset pools are supported. However, differing weighted pools could be supported in future versions. + +#### 2.1.1. Ledger Entries representing AMM instance + +##### **`AccountRoot`** ledger entry + +A new flag **`lsfAMM`** is introduced to the [**`AccountRoot`**](https://xrpl.org/accountroot.html) object. + +| Flag Name | Hex Value | Description | +| ---------- | :----------------: | :-------:| +| `lsfAMM` | 0x40000000 | If set, it indicates that the object represents an AMM instance| + +Additionally, we introduce a new field called `AMMID` to the `AccountRoot` object. It replaces directory entry to link account root and AMM object. + +| Field Name | Required? | JSON Type | Internal Type | +| ----------------- | :----------------: | :-------: | :-----------: | +| `AMMID` | :heavy_check_mark: | `string` | `UINT256` | + +`AMMID` specifies the `AMMID` as described below. + +The unique ID of the **`AccountRoot`** object, a.k.a. **`AccountRootID`** is computed as follows: +- for (i = 0; i <= 256; i--) + - Compute `AccountRootID` = `SHA512-Half`(i || [Parent Ledger Hash](https://xrpl.org/ledgerhashes.html) || `AMMID`) + - If the computed `AccountRootID` exists, repeat + - else, return `AccountRootID` + +#### **`AMM`** ledger entry +The unique ID of the new **`AMM`** object , a.k.a **`AMMID`** is computed as follows: +- Calculate the `SHA512-Half` of some of the following values: + - The `issuer` of the issued asset; + - The `currency` of the issued asset; + - The `issuer` of the second issued asset, if there exists one; + - The `currency` of the second issued asset, if there exists one; + + +The order of the fields to compute the hash is decided canonically. The **`AMMID`** associated with this **`AccountRootID`** is this hash to ensure the uniqueness of the AMM instance. The applications can look-up the **`AccountRootID`** for a specific AMM instance by providing the asset pair for that instance. + +The **`AMM`** ledger entry contains the following fields for the **`AccountRoot`** object that represents the AMM instance. + +1. **`AccountID`** specifies the ID of the `AccountRoot` object associated with this `AMM` ledger entry. +2. **`TradingFee`** specifies the fee, in basis point, to be charged to the traders for the trades executed against this AMM instance. Valid values for this field are between 0 and 1000 inclusive. A value of 1 is equivalent to 1/10 bps or 0.001%, allowing trading fee between 0% and 1%. Trading fee is a percentage of the trade size. It is charged on the asset being deposited for the `AMMDeposit` (if applicable) and `Payment` transactions and on the asset being withdrawan for the `AMMWithdraw` (if applicable) transaction. This fee is added to the AMM instance's pools and is distributed to the LPs in proportion to the `LPTokens` upon liquidity removal. + +3. **`VoteSlots`** represents an array of `Vote` objects. +4. **`AuctionSlot`** represents the `Auction` object. +5. **`LPTokenBalance`** specifies the balance of outstanding liquidity Provider Tokens (LPTokens). +6. **`Asset`** specifies the one of the assets of the AMM instance. +7. **`Asset2`** specifies the other asset of the AMM instance. + +Once the AMM **`AccountRoot`** object is created, we make sure that no further transactions can originate from this account. Conceptually, it is an account that is not owned by anyone. So every possible way of signing the transaction for this account MUST be automatically disabled. + +### 2.2. Transaction for creating AMM instance + +We define a new transaction **`AMMCreate`** specifically for creating a new AMM instance represented by an **`AccountRoot`** object and the corresponding **`AMM`** object. + +Notes: +- **`AMMCreate`** is not allowed with `LPTokens` +- **`AMMCreate`** is not allowed if the token’s issuer has `DefaultRipple` flag disabled. + +#### 2.2.1. Transaction fields for **`AMMCreate`** transaction + + +| Field Name | Required? | JSON Type | Internal Type | +| ----------------- | :----------------: | :-------: | :-----------: | +| `TransactionType` | :heavy_check_mark: | `string` | `UINT16` | + +`TransactionType` specifies the new transaction type **`AMMCreate`**. The integer value is 35. + +--- + +| Field Name | Required? | JSON Type | Internal Type | +| ---------- | :----------------: | :-------: | :-----------: | +| `Fee` | :heavy_check_mark: | `string` | `AMOUNT` | + +`Fee` specifies the integer amount of XRP, in drops, to be destroyed as a cost of creating an AMM instance. We DO NOT propose to keep a reserve for the AMM instance. + +--- + + +| Field Name | Required? | JSON Type | Internal Type | +| --------------- | :----------------: | :------------------: | :-----------: | +| `Amount` | :heavy_check_mark: | `string` or `object` | `AMOUNT` | + +`Amount` specifies one of the pool assets (XRP or token) of the AMM instance. + +--- + +| Field Name | Required? | JSON Type | Internal Type | +| --------------- | :----------------: | :-------: | :-----------: | +| `Amount2` | :heavy_check_mark: | `string` or `object` | `AMOUNT` | + +`Amount2` specifies the other pool asset of the AMM instance. + +Both `Amount` and `Amount2` that represent issued assets MUST have `value` subfields specified. + +--- + +| Field Name | Required? | JSON Type | Internal Type | +| ------------ | :----------------: | :-------: | :-----------: | +| `TradingFee` | :heavy_check_mark: | `number` | `UINT16` | + +`TradingFee` specifies the fee, in basis point, to be charged to the traders for the trades executed against the AMM instance. Trading fee is a percentage of the trading volume. Valid values for this field are between 0 and 1000 inclusive. A value of 1 is equivalent to 1/10 bps or 0.001%, allowing trading fee between 0% and 1%. + +--- + +The `AMMCreate` transaction MUST fail if the account issuing this transaction: + +i. does not have sufficient balances, OR + +ii. is NOT the `issuer` of either token AND the `RequireAuth` flag for the corresponding token is set AND the account inititaing the transaction is not authorized. + +If the transaction is successful, + +i. Two new ledger entries **`AccountRoot`** and `AMM` are created. + +ii. The regular key for the **`AccountRoot`** ledger entry is set to account zero, and the master key is disabled, effectively disabling all possible ways to sign transactions from this account. + +iii. New trustlines are created. + +#### 2.2.2. Trustlines +A successful `AMMCreate` transaction will automatically create the following trustlines: + +- Trustlines that track the balance(s) of the issued asset(s) of the AMM instance's pool(s) between the AMM instance account and the issuer. +- Trustlines that track the balance of `LPTokens` between the AMM instance and the account that initiated the transaction. `LPTokens` are uniquely identified by the following: + - issuer: AMM instance `AccountID` and; + - currency: the currency code for `LPTokens` for currency codes cur1 and cur2 is formed deterministically as follows: + + - Compute `SHA256{cur1, cur2}` + - `LPTokenID` = 0x03 + first 19 bytes from SHA256 + +The prefix 0x03 is added to identify `LPTokens` + +The `value` field is computed as follows: + +$$LPTokens = \Gamma_{A}^{W_{A}} * \Gamma_{B}^{W_{B}} $$ + +where, + +- $\Gamma_{A}$: Balance of asset $A$ +- $\Gamma_{B}$: Balance of asset $B$ +- $W_{A}$ & $W_{B}$: Normalized weights of asset $A$ and asset $B$ in the pool respectively + +Initially by default, $W_{A}$ = $W_{B}$ = 0.5 + + + +#### 2.2.3. Cost of creating AMM instance `AccountRoot` and `AMM` ledger entries + +Unlike other objects in the XRPL, there is no reserve for the `AccountRoot` and `AMM` ledger entries created by an `AMMCreate` transaction. Instead there is a higher `Fee` (~ 1 reserve) for `AMMCreate` transaction in XRP which is burned as a special transaction cost. + +### 2.3. `Deleting the AMM instance `AccountRoot` and `AMM` ledger entries` + On final withdraw (i.e. when `LPTokens` balance is 0) the AMM instance automatically deletes upto 512 trustlines. If there are fewer then 512 trustlines then `AMM` object and `AccountRoot` objects are deleted. + + However, if there are more than 512 trustlines then AMM instance is in empty state (`LPTokens` balance is 0) and we introduce a new transaction type `AMMDelete` to delete the remaining trustlines. . Any one can call `AMMDelete` transaction. `AMMDelete` also has a limit of 512 trustlines and deletes the `AMM` object and `AccountRoot` objects only if there are fewer than 512 trustlines. If there are more trustlines to delete then `AMMDelete` returns `tecINCOMPLETE` code and user should submit `AMMDelete` again. + +In order to avoid destroying assets of the AMM instance, the implementation of the `AMMWithdraw` transaction MUST guarantee that the AMM instance has no asset reserves if no account owns its `LPTokens`. + +#### 2.3.1. Fields of AMMDelete Transaction + +--- +| Field Name | Required? | JSON Type | Internal Type +| ----------------- | :----------------: | :-------: | :-----------: +| `TransactionType` | :heavy_check_mark: | `string` | `UINT16` | + +`TransactionType` specifies the new transaction type **`AMMDelete`**. The integer value is 40. + +--- + +| Field Name | Required? | JSON Type | Internal Type | +| ---------- | :----------------: | :-------: | :-----------: | +| `Asset` | :heavy_check_mark: | `object` | `ISSUE` | + +`Asset` specifies one of the assets of the AMM instance against which the transaction is to be executed. The `ISSUE` `object` may have the following subfields: + +| Field name | Required? | Description | +| :--------: | :----------------: | :-------------------------------------------------------------------------------------------------------------- | +| `issuer` | :heavy_check_mark: | specifies the unique XRPL account address of the entity issuing the currency | +| `currency` | :heavy_check_mark: | arbitrary code for currency to issue | + +If the asset is XRP, then the issuer subfield is not mentioned. + +--- +| Field Name | Required? | JSON Type | Internal Type | +| ---------- | :----------------: | :-------: | :-----------: | +| `Asset2` | :heavy_check_mark: | `object` | `ISSUE` | + +`Asset2` specifies the other asset of the AMM instance against which the transaction is to be executed. The `ISSUE` `object` may have the following subfields: + +--- + +| Field name | Required? | Description | +| :--------: | :----------------: | :-------------------------------------------------------------------------------------------------------------- | +| `issuer` | :heavy_check_mark: | specifies the unique XRPL account address of the entity issuing the currency | +| `currency` | :heavy_check_mark: | arbitrary code for currency to issue | + + +### 2.4. AMM trade transactions + +Users can trade against specific AMM instances using the new transactions **`AMMDeposit`** and **`AMMWithdraw`**, and the existing **`Payment`** transaction. + +1. `AMMDeposit`: The deposit transaction is used to add liquidity to the AMM instance pool, thus obtaining some share of the instance's pools in the form of `LPTokens`. +2. `AMMWithdraw`: The withdraw transaction is used to remove liquidity from the AMM instance pool, thus redeeming some share of the pools that one owns in the form of `LPTokens`. +3. `Payment`: The payment transaction is used to exchange one asset of the AMM instance for the other. + +#### 2.4.1. AMMDeposit transaction + +With **`AMMDeposit`** transaction, XRPL AMM allows for both: + +- **all assets** liquidity provision +- **single asset** liquidity provision + +##### 2.4.1.1 Fields for AMMDeposit transaction + + + +| Field Name | Required? | JSON Type | Internal Type +| ----------------- | :----------------: | :-------: | :-----------: +| `TransactionType` | :heavy_check_mark: | `string` | `UINT16` | + + +`TransactionType` specifies the new transaction type **`AMMDeposit`**. The integer value is 36. + +--- + +| Field Name | Required? | JSON Type | Internal Type | +| ---------- | :----------------: | :-------: | :-----------: | +| `Asset` | :heavy_check_mark: | `object` | `ISSUE` | + +`Asset` specifies one of the assets of the AMM instance against which the transaction is to be executed. The `ISSUE` `object` may have the following subfields: + +| Field name | Required? | Description | +| :--------: | :----------------: | :-------------------------------------------------------------------------------------------------------------- | +| `issuer` | :heavy_check_mark: | specifies the unique XRPL account address of the entity issuing the currency | +| `currency` | :heavy_check_mark: | arbitrary code for currency to issue | + +If the asset is XRP, then the issuer subfield is not mentioned. + +--- +| Field Name | Required? | JSON Type | Internal Type | +| ---------- | :----------------: | :-------: | :-----------: | +| `Asset2` | :heavy_check_mark: | `object` | `ISSUE` | + +`Asset2` specifies the other asset of the AMM instance against which the transaction is to be executed. + +--- +| Field Name | Required? | JSON Type | Internal Type | +| ----------------- | :-------: | :------------------: | :-----------: | +| `Amount` | | `string` or `object` | `AMOUNT` | + +`Amount` specifies the amount of one of the pools assets. If the asset is XRP, then the `Amount` is a `string` specifying the number of drops. Otherwise it is an `object` with the following subfields: + +| Field name | Required? | Description | +| :--------: | :----------------: | :-------------------------------------------------------------------------------------------------------------- | +| `issuer` | :heavy_check_mark: | specifies the unique XRPL account address of the entity issuing the currency | +| `currency` | :heavy_check_mark: | arbitrary code for currency to issue | +| `value` | | specifies the maximum amount of this currency, in decimal representation, that the trader is willing to add | + +--- + +| Field Name | Required? | JSON Type | Internal Type | +| ---------------- | :-------: | :-------: | :-----------: | +| `Amount2` | | `string` or `object` | `AMOUNT` | + +`Amount2` specifies the details of other pool asset that the trader is willing to add. + +--- + +| Field Name | Required? | JSON Type | Internal Type | +| ---------- | :-------: | :-------: | :-----------: | +| `EPrice` | | `string` | `AMOUNT` | + +`EPrice` specifies the effective-price of the token out after successful execution of the transaction. For **`AMMDeposit`** transaction, the token out is always `LPToken`. + +Note that the relative pricing does not change in case of **all-asset** deposit transaction. +`EPrice` is an invalid field for all assets deposits. It should only be specified in case of single sided deposits. + +--- + +| Field Name | Required? | JSON Type | Internal Type | +| ---------- | :-------: | :-------: | :-----------: | +| `LPTokenOut` | | `string` | `AMOUNT` | + +`LPTokenOut` specifies the amount of shares of the AMM instance pools. + +--- + +Let the following represent the pool composition of AMM instance before trade: + +- $\Gamma_{A}$: Current balance of asset $A$ +- $\Gamma_{B}$: Current balance of asset $B$ +- $\Gamma_{LPTokens}$: Current balance of outstanding `LPTokens` issued by the AMM instance + +Let the following represent the assets being deposited as a part of **`AMMDeposit`** transaction and the corresponding `LPTokens` being issued by the AMM instance. + +- $\Delta_{A}$: Balance of asset $A$ being added +- $\Delta_{B}$: Balance of asset $B$ being added +- $\Delta_{LPTokens}$: Balance of `LPTokens` issued to the LP after a successful **`AMMDeposit`** transaction + +And let $TFee$ represent the trading fee paid by the account that initiated the transaction to the AMM instance's account. This fee is added to the corresponding AMM instance pool and is proportionally divided among the `LPToken` holders. + +#### 2.4.1.2. All assets deposit (pure liquidity provision) + +If the trader deposits proportional values of both assets without changing their relative pricing, no trading fee is charged on the transaction. If $A$ +and $B$ are the assets being deposited in return for +$\Delta_{LPTokens}$, then + +$$\Delta_{A} = \left(\frac{\Delta_{LPTokens}}{\Gamma_{LPTokens}}\right) * \Gamma_{A} \tag{1}$$ + +AND + +$$\Delta_{B} = \left(\frac{\Delta_{LPTokens}}{\Gamma_{LPTokens}}\right) * \Gamma_{B} \tag{2}$$ + +Following is the updated pool composition of the AMM instance after successful transaction: + +- $\Gamma_{A} = \Gamma_{A} + \Delta_{A}$: Current new balance of asset $A$ +- $\Gamma_{B} = \Gamma_{B} + \Delta_{B}$: Current new balance of asset $B$ +- $\Gamma_{LPTokens} = \Gamma_{LPTokens} + \Delta_{LPTokens}$: Current new balance of outstanding `LPTokens` + +#### 2.4.1.3 Single asset deposit + +Let $B$ be the only asset being deposited in return for $\Delta_{LPTokens}$, then this is executed as a combination of _equal asset_ deposit and a _swap_ transaction. The trading fee is only charged on the _amount_ of asset being swapped. + +Also let + +- $F_{1} = (1-TFee)$ +- $F_{2} = \frac{(1 - \frac{TFee}{2})}{F_1}$, then + + +$$\Delta_{LPTokens} = \Gamma_{LPTokens} * \left[\frac{\frac{\Delta_{B}}{\Gamma_{B}} - \left[\left({F_2}^{\frac{1}{W_{B}}} + \frac{\Delta_{B}}{(\Gamma_{B}*F_1)}\right)^{W_B} - F_2\right]} + {1 + {\left(F_2^{\frac{1}{W_B}} + \frac{\Delta_{B}}{(\Gamma_{B}*F_1)}\right)}^{W_{B}} - F_2}\right] \tag{3}$$ + + +Similarly, +Similarly, we can derive $\Delta{B}$ from the above equation. We call this equation 4. + +Following is the updated pool composition of the AMM instance after successful trade: + +- $\Gamma_{B} = \Gamma_{B} + \Delta_{B}$: Current new balance of asset $B$ +- $\Gamma_{LPTokens} = \Gamma_{LPTokens} + \Delta_{LPTokens}$: Current new balance of outstanding `LPTokens` + + +#### 2.4.1.4. Specifying different parameters +The proposal allows for traders to specify different combinations of the above mentioned fields for **`AMMDeposit`** transaction. The implementation will determine the best possible sub operations based on trader's specifications. +We introduce the following flags to the `AMMDeposit` transaction to identify valid parameter combinations. + +| Flag Name | Hex Value | Description | +| ---------- | :----------------: | :-------:| +| `tfLPToken` | 0x00010000 | If set, it indicates `LPTokenOut` parameter and may optionally include `Amount` and `Amount2` combination| +| `tfSingleAsset` | 0x00080000 | If set, it indicates `Amount` parameter and may optionally include `LPTokenOut` parameter| +| `tfTwoAsset` | 0x00100000 | If set, it indicates `Amount` and `Amount2` parameter combination and may optionally include `LPTokenOut` paramater| + | `tfOneAssetLPToken` | 0x00200000 | If set, it indicates `Amount` and `LPTokenOut` parameter combination| + | `tfLimitLPToken` | 0x00400000 | If set, it indicates `Amount` and `EPrice` parameter combination| + | `tfWithdrawAll` | 0x00020000 | If set, it indicates proportional withdrawal of all `LPTokens`| +| `tfTwoAssetIfEmpty`| 0x00800000 | If set, it indicates that this deposit can only be submitted on an empty state AMM (LPTokens == 0)| + +If `tfTwoAssetIfEmpty` is set, both amounts have to be specified and deposited into AMM as is. It is sort of like `AMMCreate` in an empty AMM state. + + Following are the recommended valid combinations. Other invalid combinations may result in the failure of transaction. + +- `LPTokenOut`, `[Amount]`, `[Amount2]` +- `Amount`, `[LPTokenOut]` +- `Amount` , `Amount2`, `[LPTokenOut]` +- `Amount` and `LPTokenOut` +- `Amount` and `EPrice` + +Details for above combinations: + +1. Fields specified: `LPTokenOut`, `[Amount]`, `[Amount2]` and Flag: `tfLPToken` + +Such a transaction assumes proportional deposit of pools assets in exchange for the specified amount of `LPTokenOut` of the AMM instance. `Amount` and `Amount2`, if included, have to be provided both and specify minimum deposit amounts for each asset. +Deposit fails if the min deposit condition is not met + +2. Fields specified: `Amount`, `[LPTokenOut]` and Flag: `tfSingleAsset` + +Such a transaction assumes single asset deposit of the amount of asset specified by `Amount`. This is essentially an _equal_ asset deposit and a _swap_. + +If the asset to be deposited is a token, specifying the `value` field is required, else the transaction will fail. + +`LPTokenOut`, if included, specified minimum `LPTokens` amount that the user receives, else the transaction will fail. + +3. Fields specified: `Amount`, `Amount2`, `[LPTokenOut]` and Flag: `tfTwoAsset` + +Such a transaction assumes proportional deposit of pool assets with the constraints on the maximum amount of each asset that the trader is willing to deposit. + +`LPTokenOut`, if included, specified minimum `LPTokens` amount that the user receives, else the transaction will fail. + +4. Fields specified: `Amount` and `LPTokenOut` and Flag: `tfOneAssetLPToken` + +Such a transaction assumes that a single asset `Amount` is deposited to obtain some share of the AMM instance's pools represented by amount of `LPTokenOut`. Since adding liquidity to the pool with one asset changes the ratio of the assets in the two pools, thus changing the relative pricing, trading fee is charged only on the amount of the deposited asset that causes this change. + +5. Fields specified: `Amount` and `EPrice` and Flag: `tfLimitLPToken` + +Such a transaction assumes single asset deposit with the following two constraints: + +a. amount of asset1 if specified in `Amount` specifies the maximum amount of asset1 that the trader is willing to deposit + +b. The effective-price of the `LPTokenOut` traded out does not exceed the specified `EPrice` + + +Following updates after a successful `AMMDeposit` transaction: + +- The deposited asset, if XRP, is transferred from the account that initiated the transaction to the AMM instance account, thus changing the `Balance` field of each account +- The deposited asset, if tokens, are balanced between the AMM account and the issuer account trustline. +- The `LPTokenOut` ~ $\Delta_{LPTokens}$ are issued by the AMM instance account to the account that initiated the transaction and a new trustline is created, if there does not exist one. +- The pool composition is updated. Note that the conservation function is not preserved in case of liquidity provision. + +For more details refer to Appendix A. + +### 2.4.2. **`AMMWithdraw`** transaction + +With `AMMWithdraw` transaction, this proposal allows for both the following: + +- **all assets** liquidity withdrawal +- **single asset** liquidity withdrawal + +#### 2.4.2.1 Fields +| Field Name | Required? | JSON Type | Internal Type +| ----------------- | :----------------: | :-------: | :-----------: +| `TransactionType` | :heavy_check_mark: | `string` | `UINT16` | + + +`TransactionType` specifies the new transaction type **`AMMWithdraw`**. The integer value is 37. + +--- + +| Field Name | Required? | JSON Type | Internal Type | +| ---------- | :----------------: | :-------: | :-----------: | +| `Asset` | :heavy_check_mark: | `object` | `ISSUE` | + +`Asset` specifies one of the assets of the AMM instance against which the transaction is to be executed. + +--- +| Field Name | Required? | JSON Type | Internal Type | +| ---------- | :----------------: | :-------: | :-----------: | +| `Asset2` | :heavy_check_mark: | `object` | `ISSUE` | + +`Asset2` specifies the other asset of the AMM instance against which the transaction is to be executed. + +--- +| Field Name | Required? | JSON Type | Internal Type | +| ------------------ | :----------------: | :------------------: | :-----------: | +| `Amount` | | `object` or `string` | `AMOUNT` | + +`Amount` specifies one of the pools assets that the trader wants to remove. If the asset is XRP, then the `Amount` is a `string` specifying the number of drops. Otherwise it is an `object` with the following subfields: + +| Field name | Required? | Description | +| :--------: | :----------------: | :-------------------------------------------------------------------------------- | +| `issuer` | :heavy_check_mark: | specifies the XRPL address of the issuer of the currency | +| `currency` | :heavy_check_mark: | specifies the currency code of the issued currency | +| `value` | | specifies the minimum amount of this asset that the trader is willing to withdraw. | + +--- + +| Field Name | Required? | JSON Type | Internal Type | +| ----------------- | :-------: | :-------: | :-----------: | +| `Amount2` | | `string` or `object` | `AMOUNT` | + +`Amount2` specifies the other asset that the trader wants to remove. + +--- + +| Field Name | Required? | JSON Type | Internal Type | +| ---------- | :-------: | :-------: | :-----------: | +| `EPrice` | | `object` | `AMOUNT` | + +`EPrice` specifies the effective-price of the token out after successful execution of the transaction. For `AMMWithdraw` transaction, the out is either XRP or issued token. The asset in is always `LPToken`. So `EPrice` is always an `object`. + +Note that the relative pricing does not change in case of **all-asset** withdrawal. `EPrice` is an invalid field for all assets deposits. It should only be specified in case of single sided deposits. + +--- + +| Field Name | Required? | JSON Type | Internal Type | +| ---------- | :-------: | :-------: | :-----------: | +| `LPTokenIn` | | `object` | `AMOUNT` | + +`LPTokenIn` specifies the amount of shares of the AMM instance pools that the trader wants to redeem or trade in. + +--- + +Let following represent the pool composition of the AMM instance before withdrawal: + +- $\Gamma_{A}$: Current balance of asset $A$ +- $\Gamma_{B}$: Current balance of asset $B$ +- $\Gamma_{LPTokens}$: Current balance of outstanding `LPTokens` issued by the AMM instance + + +Let following represent the assets being withdrawn as a part of `AMMWithdraw` transaction and the corresponding `LPTokens` being redeemed. + +- $\Delta_A$: Balance of asset $A$ being withdrawn +- $\Delta_B$: Balance of asset $B$ being withdrawn +- $\Delta_{LPTokens}$: Balance of `LPTokens` being redeemed + +Let $TFee$ represent the trading fee paid by the trader to the AMM instance, if applicable. The fee is added to the appropriate pool and is distributed proportionally among the `LPToken` holders upon liquidity withdrawal. + +#### 2.4.2.1 All assets withdrawal (Pure liquidity withdrawal) + +If the trader withdraws proportional values of both assets without changing their relative pricing, no trading fee is charged on the transaction. +If $A$ and $B$ are the assets being withdrawn by redeeming $\Delta_{LPTokens}$, then + + +$$\Delta_A = \left(\frac{\Delta_{LPTokens}}{\Gamma_{LPTokens}}\right) * \Gamma_A \tag{5}$$ + +AND + +$$\Delta_B = \left(\frac{\Delta_{LPTokens}}{\Gamma_{LPTokens}}\right) * \Gamma_B \tag{6}$$ + +Following is the updated pool composition of the AMM instance after successful trade: + +- $\Gamma_{A} = \Gamma_{A} - \Delta_{A}$: Current new balance of asset $A$ +- $\Gamma_{B} = \Gamma_{B} - \Delta_{B}$: Current new balance of asset $B$ +- $\Gamma_{LPTokens} = \Gamma_{LPTokens} - \Delta_{LPTokens}$: Current new balance of outstanding `LPTokens` + +#### 2.4.2.2. Single asset withdrawal + +Single asset withdrawal can be conceptualized as two sub trades of _equal_ asset withdrawal and a _swap_. Let asset $B$ +be the only asset being withdrawn to redeem $\Delta_{LPTokens}$ and let +- $R = \frac{\Delta_B}{\Gamma_B}$ +- $C = R * TFee + 2 - TFee$, then + + + + +$$\Delta_{LPTokens} = {\Gamma_{LPTokens} * \left[\frac{C -(C^{\frac{1}{W_B}} - 4 * R)^{W_B}}{2}\right]} \tag{7}$$ + +Similarly, we can derive $\Delta{B}$ from the above equation. We call this equation 8. + +Following is the updated pool composition of the AMM instance after successful trade: + +- $\Gamma_B = \Gamma_B - \Delta_{B}$: Current new balance of asset $B$ +- $\Gamma_{LPTokens} = \Gamma_{LPTokens} - \Delta_{LPTokens}$: Current new balance of outstanding `LPTokens` + +#### 2.4.2.3. Specifying different parameters + +The proposal allows for traders to specify different combinations of the above mentioned fields for `AMMWithdraw` transaction. The implementation will figure out the best possible operations based on trader's specifications. + +We introduce the following six transaction flags to the `AMMWithdraw` transaction to identify valid parameter combinations. Other invalid combinations may result in the failure of transaction. + +| Flag Name | Hex Value | Description | +| ---------- | :----------------: | :-------:| +| `tfLPToken` | 0x00010000 | If set, it indicates `LPTokenIn` field parameter| +| `tfSingleAsset` | 0x00080000 | If set, it indicates `Amount` field parameter| +| `tfTwoAsset` | 0x00100000 | If set, it indicates `Amount` and `Amount2` fields parameter combination| + | `tfOneAssetLPToken` | 0x00200000 | If set, it indicates `Amount` and `LPTokenIn` fields parameter combination| + | `tfLimitLPToken` | 0x00400000 | If set, it indicates `Amount` and `EPrice` fields parameter combination| + | `tfWithdrawAll` | 0x00020000 | If set, it indicates withdrawal of both assets equivalent to all `LPTokens` held by the account| + | `tfOneAssetWithdrawAll` | 0x00040000 | If set, it indicates withdrawal of single asset equivalent to all `LPTokens` held by the account| + + +- `LPTokenIn` +- `Amount` +- `Amount` and `Amount2` +- `Amount` and `LPTokenIn` +- `Amount` and `EPrice` + +Implementation details for the above combinations: + +1. Fields specified: `LPTokenIn` + +Such a transaction assumes proportional withdrawal of pool assets for the amount of `LPTokenIn`. Since withdrawing assets proportionally from the AMM instance pools does not change the ratio of the two assets in the pool and thus does not affect the relative pricing, trading fee is not charged on such a transaction. + +2. Fields specified: `Amount` + +Such a transaction assumes withdrawal of single asset equivalent to the amount specified in `Amount` + +3. Fields specified: `Amount` and `Amount2` + +Such a transaction assumes all assets withdrawal with the constraints on the maximum amount of each asset that the trader is willing to withdraw. + +4. Fields specified: `Amount` and `LPTokenIn` + +Such a transaction assumes withdrawal of single asset specified in `Amount` proportional to the share represented by the amount of `LPTokenIn`. Since a single sided withdrawal changes the ratio of the two assets in the AMM instance pools, thus changing their relative pricing, trading fee is charged on the amount of asset1 that causes that change. + + +5. Fields specified: `Amount` and `EPrice` + + + +Such a transaction assumes withdrawal of single asset with the following constraints: + +a. amount of asset1 if specified in `Amount` specifies the minimum amount of asset1 that the trader is willing to withdraw + +b. The effective price of asset traded out does not exceed the amount specified in `EPrice` + +Following updates after a successful transaction: + +- The withdrawn asset, if XRP, is transferred from AMM instance account to the account that initiated the transaction, thus changing the `Balance` field of each account +- The withdrawn asset, if token, is balanced between the AMM instance account and the issuer account. +- The `LPTokens` ~ $\Delta_{LPTokens}$ are balanced between the AMM instance account and the account that initiated the transaction. +- The pool composition is updated. Conservation function is not preserved in case of liquidity withdrawal (and is not expected to.) + +For more details refer to Appendix B. + +### 2.5. `AMM Swap` + +In order to exchange one asset of the AMM instance's pools for another, we DO NOT introduce a new transaction. Instead, we propose to use the existing [**`Payment`**](https://xrpl.org/payment.html) transaction. + +Let the following represent the pool composition of the AMM instance before a swap. + +- $\Gamma_{A}$: Current balance of asset $A$ in the pool +- $\Gamma_{B}$: Current balance of asset $B$ in the pool + +Let the following represent the balances of assets $B$ and $A$ being swapped in and out of the AMM instance pools respectively with `Payment` transaction. + +- $\Delta_{A}$: Balance of asset $A$ being swapped out of the AMM instance's pool +- $\Delta_{B}$: Balance of asset $B$ being swapped into the AMM instance's pool + + +We can compute $\Delta_{A}$, given $\Delta_{B}$ and $TFee$ as follows: + +$$\Delta_{A} = \Gamma_{A} * \left[1 – \left(\frac{\Gamma_{B}}{\Gamma_{B}+ \Delta_{B} * \left(1-TFee\right)}\right)^\frac{W_{B}}{W_{A}}\right] \tag{9}$$ + +Similarly, we can compute $\Delta_{B}$, given $\Delta_{A}$ and $TFee$ as follows: + +$$\Delta_{B} = \Gamma_{B} * \left[\left( \frac{\Gamma_{A}}{\Gamma_{A}- \Delta_{A}} \right) ^ \frac{W_A}{W_B}-1 \right] * \frac{1}{1-TFee}\tag{10}$$ + +To change the spot-price of token $A$ traded out relative to token $B$ traded into the pool from $SP_{A}^{B}$ to $SP_{A}^{'B}$, required $\Delta_{B}$ can be computed as follows: + +$$\Delta_B = \Gamma_{B} * \left[ \left(\frac{SP_{A}^{'B}}{SP_{A}^{B}}\right)^{\left(\frac{W_A}{W_A+ W_B}\right) } - 1\right] \tag{11}$$ + +We can compute the average slippage $S(\Delta_B)$ for the token traded in as follows: + +$$S(\Delta_B) = SS_B * \Delta_B \tag{12}$$ + +where $SS_B$, the slippage slope is the derivative of the slippage when the traded amount tends to zero. + +$$SS_B = \frac{\left(1-TFee\right) * \left(W_B+W_A\right)}{2*\Gamma_B*W_A } \tag{13}$$ + +We can compute the average slippage $S(\Delta_A)$ for the token traded out as follows: + $$S(\Delta_A) = SS_{A} * \Delta_{A} \tag{14}$$ + +where $SS_A$, the slippage slope is the derivative of the slippage when the traded amount tends to zero. +$$SS_{A} = \frac{W_{A} + W_{B}}{2 * \Gamma_{B} * W_{A}} \tag{15}$$ + +The following is the updated pool composition after a successful transaction: + +- $\Gamma_{A} = \Gamma_{A} - \Delta{A}$: Current new balance of asset +$A$ +- $\Gamma_{B} = \Gamma_{B} + \Delta_{B}$: Current new balance of asset +$B$ + +Note that the conservation function is preserved, however the ratio of the two assets and hence their relative pricing changes after a successful swap. + +Following updates after a successful transaction: + +- The swapped asset, if XRP, is transferred from AMM instance account to the account that initiated the transaction or vice-versa, thus changing the `Balance` field of each account +- The swapped asset, if token, is balanced between the AMM instance account and the issuer account. +- The pool composition is updated. + +#### 2.5.1. Interpreting **`Payment`** transaction for an AMM swap +An XRPL **`Payment`** transaction represents a transfer of value from one account to another. This transaction type can be used for several types of payments. One can accomplish an equivalent of a swap with the **`Payment`** transaction. Following are the relevant fields of a **`Payment`** transaction. + +| Field Name | Required? | JSON Type | Internal Type | +| ---------- | :-------: | :-------: | :-----------: | +| `Amount` | | `Currency Amount` | `AMOUNT` | + +`Amount` field is used to specify the amount of currency that the trader wants to deliver to a destination account. For an AMM swap, this is the amount of currency that the trader wants to swap out of the pool. + +| Field Name | Required? | JSON Type | Internal Type | +| ---------- | :-------: | :-------: | :-----------: | +| `Destination` | | `String` | `AccountID` | + +`Destination` field is used to specify the account that the trader wants to deliver the currency to. This should be either the same account as the transaction or any other account that the trader wishes to send this currency amount to. + +| Field Name | Required? | JSON Type | Internal Type | +| ---------- | :-------: | :-------: | :-----------: | +| `SendMax` | | `Currency Amount` | `AMOUNT` | + +`SendMax` field is used to specify the maximum amount of currency that the trader is willing to send from the account issuing the transaction. For an AMM swap, this is the amount of currency that the trader is willing to swap into the pool. + +#### 2.5.2. Flags +The `tfLimitQuality` flag is used to specify the **quality** of trade. This is defined as the ratio of the amount in to amount out. In other words, it is the ratio of amounts in `Amount` and `SendMax` fields of a `Payment` transaction. + +For an AMM swap, if a trader wants to buy (swap out) one unit of currency specified in `Amount` field for not more than `X` units per currency specified in `SendMax`, the trader would use the following equation: +$$ SendMax = X * Amount$$ + +where `X` is equal to the `LimitSpotPrice` for the trade, i.e. the threshold on the spot-price of asset out after trade. + +#### 2.5.3. Transfer Fee +We propose that the [transfer fee](https://xrpl.org/transfer-fees.html) is not applied to `AMMCreate`, `AMMDeposit` and `AMMWithdraw` transactions. + +AMM instance never pays the transfer fee. Transfer Fee will automatically apply to `Payments` transaction and conditionally in offer-crossing through `OfferCreate`. + +## 3. Governance: Trading Fee Voting Mechanism +This proposal allows for the `TradingFee` of the AMM instance be a votable parameter. Any account that holds the corresponding `LPTokens` can cast a vote using the new `AMMVote` transaction. + +We introduce a new field `VoteSlots` associated with each AMM instance in the **`AMM`** ledger entry. The `VoteSlots` field keeps a track of up to eight active votes for the instance. + +| Field Name | Required? | JSON Type | Internal Type | +| ---------- | :-------: | :-------: | :-----------: | +| `VoteSlots` | | `array` | `ARRAY` | + +`VoteSlots` is an array of `VoteEntry` objects representing the LPs and their vote on the `TradingFee` for this AMM instance. + +### 3.1. Vote Entry object +Each member of the `VoteSlots` field is an object that describes the vote for the trading fee by the LP of that instance. A `VoteEntry` object has the following fields: + +| Field Name | Required? | JSON Type | Internal Type | +| ---------- | :-------: | :-------: | :-----------: | +| `Account` |:heavy_check_mark: | `string` | `AccountID` | + +`Account` specifies the XRPL address of the LP. + +--- + +| Field Name | Required? | JSON Type | Internal Type | +| ---------- | :-------: | :-------: | :-----------: | +| `TradingFee` | :heavy_check_mark: | `number` | `UINT16` | + +`TradingFee` specifies the fee, in basis point. Valid values for this field are between 0 and 1000 inclusive. A value of 1 is equivalent to 1/10 bps or 0.001%, allowing trading fee between 0% and 1%. + +--- + +| Field Name | Required? | JSON Type | Internal Type | +| ---------- | :-------: | :-------: | :-----------: | +| `VoteWeight` | :heavy_check_mark: | `number` | `UINT32` | + +`VoteWeight` specifies the `LPTokens` owned by the account that issued the transaction. It is specified in basis points. Valid values for this field are between 0 and 100000. A value of 1 is equivalent to 1/10 bps or 0.001%, allowing the percentage ownership in the instance between 0% and 100%. + +--- + + +`TradingFee` for the AMM instance is computed as the weighted mean of all the current votes in the `VoteSlots` field. + +$$TradingFee = \frac{\sum_{i=1}^{8}(w_i * fee_i)}{\sum_{i=1}^{8}(w_i)}$$ + +where $w_i$ and $fee_i$ represents the `VoteWeight` and the `FeeVal` of the corresponding `VoteEntry`. + +### 3.2. **`AMMVote`** transaction + +We introduce the new **`AMMVote`** transaction. Any XRPL account that holds `LPTokens` for an AMM instance may submit this transaction to vote for the trading fee for that instance. + +#### 3.2.1. Fields +| Field Name | Required? | JSON Type | Internal Type | +| ---------- | :-------: | :-------: | :-----------: | +| `Account` | :heavy_check_mark: | `string` | `AccountID` | + +`Account` specifies the XRPL account that submits the transaction. + +--- + +| Field Name | Required? | JSON Type | Internal Type | +| ----------------- | :----------------: | :-------: | :-----------: | +| `TransactionType` | :heavy_check_mark: | `string` | `UINT16` | + + +`TransactionType` specifies the new transaction type **`AMMVote`**. The integer value is 38. + +--- + +| Field Name | Required? | JSON Type | Internal Type | +| ---------- | :----------------: | :-------: | :-----------: | +| `Asset` | :heavy_check_mark: | `object` | `ISSUE` | + +`Asset` specifies one of the assets of the AMM instance against which the transaction is to be executed. + +--- +| Field Name | Required? | JSON Type | Internal Type | +| ---------- | :----------------: | :-------: | :-----------: | +| `Asset2` | :heavy_check_mark: | `object` | `ISSUE` | + +`Asset2` specifies the other asset of the AMM instance against which the transaction is to be executed. + +--- +| Field Name | Required? | JSON Type | Internal Type | +| ---------- | :-------: | :-------: | :-----------: | +| `TradingFee` | :heavy_check_mark: | `number` | `UINT16` | + +`TradingFee` specifies the fee, in basis point. Valid values for this field are between 0 and 1000 inclusive. A value of 1 is equivalent to 1/10 bps or 0.001%, allowing trading fee between 0% and 1%. + +--- + + +### 3.3. How does **`AMMVote`** transaction work? +**`AMMVote`** transaction _always_ checks if all `VoteEntry` objects in the `VoteSlots` array are up-to-date, i.e. check if there is a change in the number of `LPTokens` owned by an account in the `VoteEntry` and do the following: +1. If one or more accounts in the `VoteEntry` does not hold the `LPTokens` for this AMM instance any more, then remove that `VoteEntry` object from the `VoteSlots` array or If the number of `LPTokens` held by one or more account in the `VoteEntry` has changed, + - recompute the weights of all the votes and readjust them. Also recompute the `TradingFee` for the AMM instance and update it in the `AMM` object of that instance. + +2. Check the `LPTokens` held by the account submitting the `AMMVote` transaction. If the account does not hold any `LPTokens`, then the transaction fails with an error code. Otherwise, there are following cases: + - If there are fewer than eight `VoteEntry` objects in the updated `VoteSlots` array, then: + a. Compute the weight of the current vote, add the computed weight of that vote as `VoteWeight` field to the object and readjust in the object. + b. Add that `FeeVal` of the current vote to the `VoteEntry` object. + c. Compute the `TradingFee` for the AMM instance as described above and update the `TradingFee` field value in the `AMM` object of the AMM instance. + + - If all eight `VoteEntry` slots are full, but this account holds more `LPTokens`, i.e. higher `VoteWeight` than the `VoteEntry` object with the lowest `VoteWeight`, this vote will replace the `VoteEntry` with the lowest `VoteWeight`. (Followed by same steps as above.) + + - If the account that submitted the transaction already holds a vote, then update that `VoteEntry` and `TradingFee` based on the transaction fields. + +## 4. Continuous Auction Mechanism +We introduce a novel mechanism for an AMM instance to auction-off the trading advantages to users (arbitrageurs) at a **discounted** `TradingFee` for a 24 hour slot. Any account that owns corresponding `LPTokens` can bid for the auction slot of that AMM instance. This is a continuous auction, any account can bid for the slot any time. Part of the proceeds from the auction, i.e. `LPTokens` are refunded to the current slot-holder computed on a pro rata basis. Remaining part of the proceeds - in the units of `LPTokens`- is burnt, thus effectively increasing the LPs shares. + +### 4.1. Mechanics +The bid price to purchase the slot must adjust dynamically to function as an auction. If the slot is full, i.e. if an account owns the auction slot, the following should hold: +- the price should drop as the slot gets older. +- one must pay more (per unit time) than the value at which the slot was bought. +- the previous slot holder may lose their slot, in which case they receive a pro-rata refund (for their remaining time) and the rest goes to the pool (LPs). + +The complex mechanism is how the price to buy the slot should drop as the occupied slot gets older. We introduce the slot price-schedule algorithm to answer the following questions: +1. How is the additional price one must pay per unit time to replace the holder of an existing slot determined? +2. How is the additional amount shared between the pool and the account losing its slot? +3. What is the amount per unit time for a slot when the slot is empty? + +#### 4.1.1. Slot pricing +The minimum price to buy a slot for 24-hour period is called `MinSlotPrice` (`M`). Total slot time of 24-hours is divided into 20 equal intervals. An auction slot can be in one of the following states at any given time: + +1. **Empty** - no account currently holds the slot. + +2. **Occupied** - an account owns the slot with at least 5% of the remaining slot time (i.e. in one of the 1-19 intervals). + +3. **Tailing** - an account owns the slot with less than 5% of the remaining time (i.e, in the last interval). + +The slot-holder owns the slot privileges when in State 2 or 3. + +#### Slot pricing scheduling algorithm +I. Slot state - **Empty** or **Tailing**, then + +Slot Price = `M` + +II. Slot state - **Occupied**, then + +Let the price at which the slot is bought be `B` - specified in `Amount` of `LPTokens`. Let `t` represent the fraction of used slot time for the current slot-holder. Note that for each interval `t` has a discrete value (0.05, 0.1, , ..., 1). Let `M` represent the minimum slot price. + +| Interval | `t` | +| :---------- | :----------------: | +| (0,1] | 0.05 | +| (1,2] | 0.1 | +| (19, 20] | 1 | + + +The algorithm to compute the minimum bid price of the slot at any given time enforces the following rules: + +1. The minimum bid price of the slot in the first interval is, i.e. for `t` = 0.05: + +$$ f(t) = B * 1.05 + M $$ + +1. The slot price decays exponentially over time. For the price to decay very very slowly for most of the time intervals (~95%) and instantly drop to the **MinSlotPrice** as the slot gets closer to the expiration time (~5%), we choose a heuristic function that produces this behavior. The following equation determines the minimum bid price of the slot for $t \in [0.1, 1]$ : + +$$ f(t) = B * 1.05*(1-t^{60}) + M $$ + +Notice that the slot price approaches `M` as the slot approaches expiration (i.e., as `t` approaches 1). + +1. The revenue from a successful `AMMBid` transaction is split between the current slot-holder and the pool. We propose to _always_ refund the current slot-holder of the remaining value of the slot computed from the price at which they bought the slot. +$$ f(t) = (1-t)*B $$ + +The remaining `LPTokens` are burnt/deleted, effectively increasing the LPs share in the pool. + +4. Let `X` represent the minimum bid price computed by the price-scheduling algorithm, then, + - If (`MinBidPrice` && `MaxBidPrice`): + - return + - If (`MinBidPrice`):m + - if (`MinBidPrice` <= `X`): return `X` + - else: return `MinBidPrice` + - elif (`MaxBidPrice`): + - if (`MaxBidPrice`>= `X`): return `X` + - else: return `MaxBidPrice` + +We implement the following as the **MinSlotPrice**: +$$M = LPTokens * \frac{tradingFee}{25}$$ +#### 4.1.2. `AuctionSlot` field +We introduce a new object field `AuctionSlot` in the **`AMM`** object associated with each AMM instance. The `AuctionSlot` field has the following subfields: + +| Field Name | Required? | JSON Type | Internal Type | +| ---------- | :-------: | :-------: | :-----------: | +| `Account` | :heavy_check_mark: | `string` | `AccountID` | + +`Account` represents the XRPL account that currently owns the auction slot. + +--- + +| Field Name | Required? | JSON Type | Internal Type | +| ---------- | :-------: | :-------: | :-----------: | +| `Expiration` | :heavy_check_mark: | `string` | `UINT32` | + +`Expiration` represents the number of seconds since the [Ripple Epoch](https://xrpl.org/basic-data-types.html#specifying-time). This marks the end of the time from when slot was bought. + +--- + +| Field Name | Required? | JSON Type | Internal Type | +| ---------- | :-------: | :-------: | :-----------: | +| `DiscountedFee` | :heavy_check_mark: | `string` | `UINT32` | + +`DiscountedFee` represents the `TradingFee` to be charged to this account for trading against the AMM instance. By default it is 0. + +--- + +| Field Name | Required? | JSON Type | Internal Type | +| ---------- | :-------: | :-------: | :-----------: | +| `Price` | :heavy_check_mark: | `string` | `AMOUNT` | + +`Price` represents the price paid for the slot specified in units of `LPTokens` of the AMM instance. + +--- + +| Field Name | Required? | JSON Type | Internal Type | +| ---------- | :-------: | :-------: | :-----------: | +| `AuthAccounts` | | `array` | `Array` | + +`AuthAccounts` represents an array of XRPL account IDs that are authorized to trade at the discounted fee against the AMM instance. The proposal allows for up to a maximum of four accounts. + +--- + +#### 4.1.3. **`AMMBid`** transaction +We introduce a new transaction **`AMMBid`** to place a bid for the auction slot. The transaction may have the following optional and required fields: + +| Field Name | Required? | JSON Type | Internal Type | +| ---------- | :-------: | :-------: | :-----------: | +| `Account` | :heavy_check_mark: | `string` | `AccountID` | + +`Account` represents the XRPL account that submits the transaction. + +--- + +| Field Name | Required? | JSON Type | Internal Type | +| ----------------- | :----------------: | :-------: | :-----------: | +| `TransactionType` | :heavy_check_mark: | `string` | `UINT16` | + +`TransactionType` specifies the new transaction type **`AMMBid`**. The integer value is 39. + +--- + +| Field Name | Required? | JSON Type | Internal Type | +| ---------- | :----------------: | :-------: | :-----------: | +| `Asset` | :heavy_check_mark: | `object` | `ISSUE` | + +`Asset` specifies one of the assets of the AMM instance against which the transaction is to be executed. + +--- + +| Field Name | Required? | JSON Type | Internal Type | +| ---------- | :----------------: | :-------: | :-----------: | +| `Asset2` | :heavy_check_mark: | `object` | `ISSUE` | + +`Asset2` specifies the other asset of the AMM instance against which the transaction is to be executed. + +--- +| Field Name | Required? | JSON Type | Internal Type | +| ---------- | :-------: | :-------: | :-----------: | +| `MinBidPrice` | | `string` | `STRING NUMBER` | + +`MinBidPrice` represents the minimum price that the bidder wants to pay for the slot. It is specified in units of `LPTokens`. This is not a required field. If specified let `MinBidPrice` be `X` and let the slot-price computed by price scheduling algorithm be `Y`, then bidder always pays the max(X, Y). + +--- + +| Field Name | Required? | JSON Type | Internal Type | +| ---------- | :-------: | :-------: | :-----------: | +| `AuthAccounts` | | `array` | `Array` | + +`AuthAccounts` represents an array of XRPL account IDs that are authorized to trade at the discounted fee against the AMM instance. The proposal allows for up to a maximum of four accounts. + +--- + +| Field Name | Required? | JSON Type | Internal Type | +| ---------- | :-------: | :-------: | :-----------: | +| `MaxBidPrice` | | `string` | `STRING NUMBER` | + +`MaxBidPrice` represents the maximum price that the bidder wants to pay for the slot. It is specified in units of `LPTokens`. This is not a required field. If specified let `MaxBidPrice` be `X` and let the slot-price computed by price scheduling slgorithm be `Y`, then bidder always pays the min(X, Y). + +--- + +## Appendices +### Appendix A. Specifying different parameters for **`AMMDeposit`** transaction + +The proposal allows for traders to specify different combinations of the fields for **`AMMDeposit`** transaction. The implementation will figure out the best possible sub operations based on trader's specifications. Here are the recommended valid combinations. Other invalid combinations may result in the failure of transaction. + +- `LPTokenOut`, `[Amount]`, `[Amount2]` +- `Amount`, `[LPTokenOut]` +- `Amount` , `Amount2`, `[LPTokenOut]` +- `Amount` and `LPTokenOut` +- `Amount` and `EPrice` + +Implementation details for above combinations: + +1. Fields specified: `LPTokenOut`, `[Amount]`, `[Amount2]` + +Such a transaction assumes proportional deposit of pools assets in exchange for the specified amount of `LPTokenOut` of the AMM instance. + +- Use equations 1 & 2 to compute the amount of each asset to be deposited, given the amount of $\Delta_{LPTokenOut}$ specified as `LPTokenOut` + +If the account that initiated the transaction holds sufficient balances, the transaction is successful. It fails otherwise with an error code. + +Similarly, if `[Amount]`, `[Amount2]` are specified and the amount of either asset computed above is less than the amounts specified in these fields, then the transaction fails. + + +2. Fields specified: `Amount`, `[LPTokenOut]` + +Such a transaction assumes single asset deposit of the amount of asset specified by `Amount`. This is essentially an _equal_ asset deposit and a _swap_. + +- Check if the account that initiated the transaction holds the amount of `Amount`. +- If not, the transaction fails with an error code. Otherwise, + - Use equation 3 to compute amount of `LPTokenOut` ~ $\Delta_{LPTokenOut}$ to be issued, given either the amount of drops of `XRP` or the amount of tokens in `Amount`. + +If the asset to be deposited is a token, specifying the `value` field is required, else the transaction will fail. + +If `LPTokenOut` field exists, and the amount of `LPTokenOut` computed above is less than the that specified in this field, then the transaction fails. + +3. Fields specified: `Amount`, `Amount2` and `[LPTokenOut]` + +Such a transaction assumes proportional deposit of pool assets with the constraints on the maximum amount of each asset that the trader is willing to deposit. + +- Use equation 1 to compute the amount of $\Delta_{LPTokenOut}$, given the amount in `Amount`. Let this be `Z` +- Use equation 2 to compute the amount of asset2, given $\Delta_{LPTokenOut}$ ~ `Z`. Let the computed amount of asset2 be `X`. + - If `X` <= amount in `Amount2`: + - The amount of asset1 to be deposited is the one specified in `Amount` + - The amount of asset2 to be deposited is `X` + - The amount of `LPTokenOut` to be issued is `Z` + - If X > amount in `Amount2`: + - Use equation 2 to compute $\Delta_{LPTokenOut}$, given the amount in `Amount2`. Let this be `W` + - Use equation 1 to compute the amount of asset1, given $\Delta_{LPTokenOut}$ ~ `W` from above. Let the computed amount of asset1 be `Y` + - If `Y` <= amount in `Amount`: + - The amount of asset1 to be deposited is `Y` + - The amount of asset2 to be deposited is the one specified in `Amount2` + - The amount of `LPTokenOut` to be issued is `W` + +else, failed transaction. + +If `LPTokenOut` field exists, and the amount of `LPTokenOut` computed above is less than the that specified in this field, then the transaction fails. + +4. Fields specified: `Amount` and `LPTokenOut` + +Such a transaction assumes that a single asset `asset1` is deposited to obtain some share of the AMM instance's pools represented by amount in `LPTokenOut`. Since adding liquidity to the pool with one asset changes the ratio of the assets in the two pools, thus changing the relative pricing, trading fee is charged on the amount of the deposited asset that causes this change. + +- Check if the account that initiated the transaction holds the amount of `Amount`. +- If not, the transaction fails with an error code. Otherwise, + - Use equation 4 to compute the amount of asset1 to be deposited, given $\Delta_{LPTokenOut}$ represented by amount of `LPTokenOut` + +5. Fields specified: `Amount` and `EPrice` + +Such a transaction assumes single asset deposit with the following two constraints: + +a. amount of asset1 if specified in `Amount` specifies the maximum amount of asset1 that the trader is willing to deposit + +b. The effective-price of the `LPToken` traded out does not exceed the specified `EPrice` + +- Use equation 3 to compute the amount of `LPTokenOut` out, given the amount of `Amount`. Let this be `X` +- Use equation `III` to compute the effective-price of the trade given `Amount` amount as the asset in and the `LPTokens` amount ~ `X` as asset out. Let this be `Y`. +- If `Y` <= amount in `EPrice`: + - The amount of asset1 to be deposited is given by amount in `Amount` + - The amount of `LPTokenOut` to be issued is `X` +- If (`Y`>`EPrice`) OR (amount in `Amount` does not exist): + - Use equations 3 & `III` and the given `EPrice` to compute the following two variables: + - The amount of asset1 in. Let this be `Q` + - The amount of `LPTokenOut` out. Let this be `W` + - The amount of asset1 to be deposited is `Q` + - The amount of `LPTokenOut` to be issued is `W` + + +Following updates after a successful **`AMMDeposit`** transaction: + +- The deposited asset, if XRP, is transferred from account that initiated the transaction to AMM instance account, thus changing the `Balance` field of each account +- The deposited asset, if token, are balanced between the AMM account and the issuer account trustline. +- The `LPTokenOut` are issued by the AMM instance account to the account that initiated the transaction and a new trustline is created, if there does not exist one. +- The pool composition is updated. Note that the conservation function is not preserved in case of liquidity provision (and is not expected to.) + +### Appendix B. Specifying different parameters for **`AMMWithdraw`** transaction + +The proposal allows for traders to specify different combinations of the above mentioned fields for **`AMMWithdraw`** transaction. The implementation will figure out the best possible operations based on trader's specifications. Here are the recommended possible combinations. Other invalid combinations may result in the failure of transaction. + +- `LPTokenIn` +- `Amount` +- `Amount` and `Amount2` +- `Amount` and `LPTokenIn` +- `Amount` and `EPrice` + +Implementation details for the above combinations: + +1. Fields specified: `LPTokenIn` + +Such a transaction assumes proportional withdrawal of pool assets for the amount of `LPTokenIn`. Since withdrawing assets proportionally from the AMM instance pools does not change the ratio of the two assets in the pool and thus does not affect the relative pricing, trading fee is not charged on such a transaction. + +- Check if the account that initiated the transaction holds the amount of `LPTokenIn`. +- If not, the transaction fails with an error code. Otherwise, + - Use equations 5 & 6 to compute the amount of both the assets in the AMM instance pool, given the redeemed $\Delta_{LPTokenIn}$ represented by `LPTokenIn` + + +2. Fields specified: `Amount` + +Such a transaction assumes withdrawal of single asset equivalent to the amount specified in `Amount` + +- Use equation 7 to compute the $\Delta_{LPTokenIn}$, given the amount in `Amount`. + +If the account that submitted the transaction holds the amount of $\Delta_{LPTokenIn}$ computed above, then the transaction is successful. It fails otherwise. + + +3. Fields specified: `Amount` and `Amount2` + +Such a transaction assumes all assets withdrawal with the constraints on the maximum amount of each asset that the trader is willing to withdraw. + +- Use equation 5 to compute $\Delta_{LPTokenIn}$, given the amount in `Amount`. Let this be `Z` +- Use equation 6 to compute the amount of asset2, given $\Delta_{LPTokenIn}$ ~ `Z`. Let the computed amount of asset2 be `X` +- If `X` <= amount in `Amount2`: + - The amount of asset1 to be withdrawn is the one specified in `Amount` + - The amount of asset2 to be withdrawn is `X` + - The amount of `LPTokenIn` redeemed is `Z` +- If `X`> amount in `Amount2`: + - Use equation 5 to compute $\Delta_{LPTokenIn}$, given the amount in `Amount2`. Let this be `Q` + - Use equation 6 to compute the amount of asset1, given $\Delta_{LPTokenIn}$ ~ `Q`. Let the computed amount of asset1 be `W` + - The amount of asset2 to be withdrawn is the one specified in `Amount2` + - The amount of asset1 to be withdrawn is `W` + - The amount of `LPTokenIn` redeemed is `Q` + +The transaction MUST fail if the account initiating the transaction does not hold the amount of `LPTokenIn` computed above. + + +4. Fields specified: `Amount` and `LPTokenIn` + +Such a transaction assumes withdrawal of single asset specified in `Amount` proportional to the share represented by the amount of `LPTokenIn`. Since a single sided withdrawal changes the ratio of the two assets in the AMM instance pools, thus changing their relative pricing, trading fee is charged on the amount of asset1 that causes that change. + +- Check if the account that initiated the transaction holds the amount of `LPTokenIn`. +- If not, the transaction fails with an error code. Otherwise, + - Use equation 8 to compute the amount of asset1, given the redeemed $\Delta_{LPTokenIn}$ represented by `LPTokenIn`. Let this be `Y`. + - If (amount exists for `Amount` & `Y` >= amount in `Amount`) || (amount field does not exist for `Amount`): + - The amount of asset out is `Y` + - The amount of `LPTokens` redeemed is `LPTokenIn` + +else transaction fails. + + +5. Fields specified: `Amount` and `EPrice` + + + +Such a transaction assumes withdrawal of single asset with the following constraints: + +a. amount of asset1 if specified in `Amount` specifies the minimum amount of asset1 that the trader is willing to withdraw + +b. The effective price of asset traded out does not exceed the amount specified in `EPrice` + +- Use equations 8 & `III` and amount in `EPrice`to compute the two variables, i.e., + - asset in as `LPTokenIn`. Let this be `X` + - asset out as that in `Amount`. Let this be `Y` +- If (amount exists for `Amount` & `Y` >= amount in `Amount`) || (amount field does not exist for `Amount`): + - The amount of assetOut is given by `Y` + - The amount of LPTokens is given by `X` + +else transaction fails. + +Following updates after a successful **`AMMWithdraw`** transaction: + +- The withdrawn asset, if XRP, is transferred from AMM instance account to the account that initiated the transaction, thus changing the `Balance` field of each account +- The withdrawn asset, if token, is balanced between the AMM instance account and the issuer account. +- The `LPTokens` ~ $\Delta_{LPTokenIn}$ are balanced between the AMM instance account and the account that initiated the transaction. +- The pool composition is updated. Conservation function is not preserved in case of liquidity withdrawal (and is not expected to.) + +## Implementation +A proposed reference implementation is in progress here: https://github.com/XRPLF/rippled/pull/4294 From 745774d88f2b3e31f6973d3c80be827d4301daa4 Mon Sep 17 00:00:00 2001 From: Aanchal Malhotra Date: Tue, 29 Aug 2023 19:49:40 -0400 Subject: [PATCH 02/17] Update XLS-30/README.md Co-authored-by: Elliot Lee --- XLS-30/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/XLS-30/README.md b/XLS-30/README.md index 2661e038..c5b4237d 100644 --- a/XLS-30/README.md +++ b/XLS-30/README.md @@ -9,7 +9,7 @@ # Automated Market Maker on XRP Ledger ### Abstract -The XRPL decentralized exchange (DeX) currently provides liquidity exclusively by manual market making and order books. This proposal adds non-custodial automated market maker (AMM) as a native feature to the XRPL DeX in a way that provides increased returns to those who provide liquidity for the AMM and minimizes the risk of losses due to volatility. +The XRPL decentralized exchange (DEX) currently provides liquidity exclusively by manual market making and order books. This proposal adds non-custodial automated market maker (AMM) as a native feature to the XRPL DEX in a way that provides increased returns to those who provide liquidity for the AMM and minimizes the risk of losses due to volatility. We propose a unique mechanism where the AMM instance continuously auctions off trading advantages to arbitrageurs, charging them and giving these earnings to its liquidity providers. This allows liquidity providers to take a large share of the profits that would normally be taken by arbitrageurs. From dae75ca65f72ef3b27309e868fd6f245005e8541 Mon Sep 17 00:00:00 2001 From: Aanchal Malhotra Date: Tue, 29 Aug 2023 19:49:51 -0400 Subject: [PATCH 03/17] Update XLS-30/README.md Co-authored-by: Elliot Lee --- XLS-30/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/XLS-30/README.md b/XLS-30/README.md index c5b4237d..fe76ba1a 100644 --- a/XLS-30/README.md +++ b/XLS-30/README.md @@ -20,7 +20,7 @@ The AMM instances also provide governance rights to the largest share holders of XRPL's AMM based DeX interacts with XRPL's limit order book (LOB) based DeX so that users of AMM pools have access to all order flow and liquidity on LOB DeX, and vice versa. The payment and order placement transactors automatically determine whether swapping within a liquidity pool or through the order book will provide the best price for the user and execute accordingly. Pathfinding considers paths with both order books and AMMs in various combinations to improve the overall exchange rate. ### 1. Introduction -AMMs are agents that pool liquidity and make it available to traders according to a predetermined algorithm. This is a proposal for geometric mean market maker (GM3) based DeX as a native XRPL feature. GM3 algorithmically discovers a fair exchange value, stabilized by arbitrage, to automatically produce liquidity. On XRPL, this would provide liquidity pools between XRP and issued assets as well as between any two issued assets. Arbitrageurs play a significant role in keeping the AMM DeX in a stable state with respect to external markets. +AMMs are agents that pool liquidity and make it available to traders according to a predetermined algorithm. This is a proposal for geometric mean market maker (GM3)-based DEX as a native XRPL feature. GM3 algorithmically discovers a fair exchange value, stabilized by arbitrage, to automatically produce liquidity. On XRPL, this would provide liquidity pools between XRP and issued assets as well as between any two issued assets. Arbitrageurs play a significant role in keeping the AMM DEX in a stable state with respect to external markets. Several things that contribute to the costs that trading imposes on AMM pools are naturally much less significant on XRPL: From a029f2ca2f0b40820e6ed12d5f39e01730335f93 Mon Sep 17 00:00:00 2001 From: Aanchal Malhotra Date: Tue, 29 Aug 2023 19:50:29 -0400 Subject: [PATCH 04/17] Update XLS-30/README.md Co-authored-by: Elliot Lee --- XLS-30/README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/XLS-30/README.md b/XLS-30/README.md index fe76ba1a..75e6b6d6 100644 --- a/XLS-30/README.md +++ b/XLS-30/README.md @@ -441,7 +441,6 @@ $$\Delta_{LPTokens} = \Gamma_{LPTokens} * \left[\frac{\frac{\Delta_{B}}{\Gamma_{ {1 + {\left(F_2^{\frac{1}{W_B}} + \frac{\Delta_{B}}{(\Gamma_{B}*F_1)}\right)}^{W_{B}} - F_2}\right] \tag{3}$$ -Similarly, Similarly, we can derive $\Delta{B}$ from the above equation. We call this equation 4. Following is the updated pool composition of the AMM instance after successful trade: From 42d4a0b9b6623537bfdc98e0462105a525d8fbe9 Mon Sep 17 00:00:00 2001 From: Aanchal Malhotra Date: Tue, 29 Aug 2023 19:50:38 -0400 Subject: [PATCH 05/17] Update XLS-30/README.md Co-authored-by: Elliot Lee --- XLS-30/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/XLS-30/README.md b/XLS-30/README.md index 75e6b6d6..ddaed454 100644 --- a/XLS-30/README.md +++ b/XLS-30/README.md @@ -17,7 +17,7 @@ The AMM instance charges a spread on the trades that change the ratio of tokens The AMM instances also provide governance rights to the largest share holders of the AMM instance. This allows them to vote on the trading fee the instance charges. -XRPL's AMM based DeX interacts with XRPL's limit order book (LOB) based DeX so that users of AMM pools have access to all order flow and liquidity on LOB DeX, and vice versa. The payment and order placement transactors automatically determine whether swapping within a liquidity pool or through the order book will provide the best price for the user and execute accordingly. Pathfinding considers paths with both order books and AMMs in various combinations to improve the overall exchange rate. +XRPL's AMM based DEX interacts with XRPL's limit order book (LOB)-based DEX so that users of AMM pools have access to all order flow and liquidity on LOB DEX, and vice versa. The payment and order placement transactors automatically determine whether swapping within a liquidity pool or through the order book will provide the best price for the user and execute accordingly. Pathfinding considers paths with both order books and AMMs in various combinations to improve the overall exchange rate. ### 1. Introduction AMMs are agents that pool liquidity and make it available to traders according to a predetermined algorithm. This is a proposal for geometric mean market maker (GM3)-based DEX as a native XRPL feature. GM3 algorithmically discovers a fair exchange value, stabilized by arbitrage, to automatically produce liquidity. On XRPL, this would provide liquidity pools between XRP and issued assets as well as between any two issued assets. Arbitrageurs play a significant role in keeping the AMM DEX in a stable state with respect to external markets. From 8594aa023e6b8ba1f1a92524718cd597aa1cee00 Mon Sep 17 00:00:00 2001 From: Elliot Lee Date: Tue, 12 Sep 2023 09:29:31 -0700 Subject: [PATCH 06/17] fix typos --- XLS-30/README.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/XLS-30/README.md b/XLS-30/README.md index ddaed454..46332973 100644 --- a/XLS-30/README.md +++ b/XLS-30/README.md @@ -62,7 +62,7 @@ $$SP_{A}^{B} = \frac{\frac{\Gamma_B}{W_B}}{\frac{\Gamma_A}{W_A}} * \frac{1}{\le $$EP_{A}^{B} = \frac{\Delta_B}{\Delta_A} \tag{III}$$ - + 6. **Slippage**: Slippage is defined as the percentage change in the effective price of a trade relative to the pre-swap spot-price. @@ -108,7 +108,7 @@ As slot holder will have significant advantages for arbitrage, it’s expected t ### 2.1. On-Ledger Objects -We propose the existing **`AccountRoot`** object together with a new ledger object **`AMM`** to represent an AMM instance. Currently, the **`AccountRoot`** object type describes a single account, its settings, and XRP balance on the XRP ledger. The **`AccountRoot`** and the **`AMM`** objects that represent an AMM instance can be created using the new **`AMMCreate`** transaction. XRP balance of the AMM instance pools is always tracked via the existing `Balance` field of the **`AccountRoot`** object. The issued asset balances of the AMM instance pools and **`LPTokens`** are automatically tracked via trustlines. The AMM can be traded against using the new **`AMMDeposit`** and **`AMMWithdraw`** and the existing **`Payment`** transactions. Additionally, the AMM instance in "empty" state can be deleted using the `AMMDelete` transaction. +We propose the existing **`AccountRoot`** object together with a new ledger object **`AMM`** to represent an AMM instance. Currently, the **`AccountRoot`** object type describes a single account, its settings, and XRP balance on the XRP ledger. The **`AccountRoot`** and the **`AMM`** objects that represent an AMM instance can be created using the new **`AMMCreate`** transaction. XRP balance of the AMM instance pools is always tracked via the existing `Balance` field of the **`AccountRoot`** object. The issued asset balances of the AMM instance pools and **`LPTokens`** are automatically tracked via trust lines. The AMM can be traded against using the new **`AMMDeposit`** and **`AMMWithdraw`** and the existing **`Payment`** transactions. Additionally, the AMM instance in "empty" state can be deleted using the `AMMDelete` transaction. Note that in this version, only equal-weighted two asset pools are supported. However, differing weighted pools could be supported in future versions. @@ -150,7 +150,7 @@ The order of the fields to compute the hash is decided canonically. The **`AMMID The **`AMM`** ledger entry contains the following fields for the **`AccountRoot`** object that represents the AMM instance. 1. **`AccountID`** specifies the ID of the `AccountRoot` object associated with this `AMM` ledger entry. -2. **`TradingFee`** specifies the fee, in basis point, to be charged to the traders for the trades executed against this AMM instance. Valid values for this field are between 0 and 1000 inclusive. A value of 1 is equivalent to 1/10 bps or 0.001%, allowing trading fee between 0% and 1%. Trading fee is a percentage of the trade size. It is charged on the asset being deposited for the `AMMDeposit` (if applicable) and `Payment` transactions and on the asset being withdrawan for the `AMMWithdraw` (if applicable) transaction. This fee is added to the AMM instance's pools and is distributed to the LPs in proportion to the `LPTokens` upon liquidity removal. +2. **`TradingFee`** specifies the fee, in basis point, to be charged to the traders for the trades executed against this AMM instance. Valid values for this field are between 0 and 1000 inclusive. A value of 1 is equivalent to 1/10 bps or 0.001%, allowing trading fee between 0% and 1%. Trading fee is a percentage of the trade size. It is charged on the asset being deposited for the `AMMDeposit` (if applicable) and `Payment` transactions and on the asset being withdrawn for the `AMMWithdraw` (if applicable) transaction. This fee is added to the AMM instance's pools and is distributed to the LPs in proportion to the `LPTokens` upon liquidity removal. 3. **`VoteSlots`** represents an array of `Vote` objects. 4. **`AuctionSlot`** represents the `Auction` object. @@ -218,7 +218,7 @@ The `AMMCreate` transaction MUST fail if the account issuing this transaction: i. does not have sufficient balances, OR -ii. is NOT the `issuer` of either token AND the `RequireAuth` flag for the corresponding token is set AND the account inititaing the transaction is not authorized. +ii. is NOT the `issuer` of either token AND the `RequireAuth` flag for the corresponding token is set AND the account initiating the transaction is not authorized. If the transaction is successful, @@ -226,10 +226,10 @@ i. Two new ledger entries **`AccountRoot`** and `AMM` are created. ii. The regular key for the **`AccountRoot`** ledger entry is set to account zero, and the master key is disabled, effectively disabling all possible ways to sign transactions from this account. -iii. New trustlines are created. +iii. New trust lines are created. #### 2.2.2. Trustlines -A successful `AMMCreate` transaction will automatically create the following trustlines: +A successful `AMMCreate` transaction will automatically create the following trust lines: - Trustlines that track the balance(s) of the issued asset(s) of the AMM instance's pool(s) between the AMM instance account and the issuer. - Trustlines that track the balance of `LPTokens` between the AMM instance and the account that initiated the transaction. `LPTokens` are uniquely identified by the following: @@ -260,7 +260,7 @@ Initially by default, $W_{A}$ = $W_{B}$ = 0.5 Unlike other objects in the XRPL, there is no reserve for the `AccountRoot` and `AMM` ledger entries created by an `AMMCreate` transaction. Instead there is a higher `Fee` (~ 1 reserve) for `AMMCreate` transaction in XRP which is burned as a special transaction cost. ### 2.3. `Deleting the AMM instance `AccountRoot` and `AMM` ledger entries` - On final withdraw (i.e. when `LPTokens` balance is 0) the AMM instance automatically deletes upto 512 trustlines. If there are fewer then 512 trustlines then `AMM` object and `AccountRoot` objects are deleted. + On final withdraw (i.e. when `LPTokens` balance is 0) the AMM instance automatically deletes up to 512 trust lines. If there are fewer then 512 trustlines then `AMM` object and `AccountRoot` objects are deleted. However, if there are more than 512 trustlines then AMM instance is in empty state (`LPTokens` balance is 0) and we introduce a new transaction type `AMMDelete` to delete the remaining trustlines. . Any one can call `AMMDelete` transaction. `AMMDelete` also has a limit of 512 trustlines and deletes the `AMM` object and `AccountRoot` objects only if there are fewer than 512 trustlines. If there are more trustlines to delete then `AMMDelete` returns `tecINCOMPLETE` code and user should submit `AMMDelete` again. @@ -457,7 +457,7 @@ We introduce the following flags to the `AMMDeposit` transaction to identify val | ---------- | :----------------: | :-------:| | `tfLPToken` | 0x00010000 | If set, it indicates `LPTokenOut` parameter and may optionally include `Amount` and `Amount2` combination| | `tfSingleAsset` | 0x00080000 | If set, it indicates `Amount` parameter and may optionally include `LPTokenOut` parameter| -| `tfTwoAsset` | 0x00100000 | If set, it indicates `Amount` and `Amount2` parameter combination and may optionally include `LPTokenOut` paramater| +| `tfTwoAsset` | 0x00100000 | If set, it indicates `Amount` and `Amount2` parameter combination and may optionally include `LPTokenOut` parameter| | `tfOneAssetLPToken` | 0x00200000 | If set, it indicates `Amount` and `LPTokenOut` parameter combination| | `tfLimitLPToken` | 0x00400000 | If set, it indicates `Amount` and `EPrice` parameter combination| | `tfWithdrawAll` | 0x00020000 | If set, it indicates proportional withdrawal of all `LPTokens`| @@ -510,7 +510,7 @@ b. The effective-price of the `LPTokenOut` traded out does not exceed the specif Following updates after a successful `AMMDeposit` transaction: - The deposited asset, if XRP, is transferred from the account that initiated the transaction to the AMM instance account, thus changing the `Balance` field of each account -- The deposited asset, if tokens, are balanced between the AMM account and the issuer account trustline. +- The deposited asset, if tokens, are balanced between the AMM account and the issuer account trust line. - The `LPTokenOut` ~ $\Delta_{LPTokens}$ are issued by the AMM instance account to the account that initiated the transaction and a new trustline is created, if there does not exist one. - The pool composition is updated. Note that the conservation function is not preserved in case of liquidity provision. @@ -1062,7 +1062,7 @@ We introduce a new transaction **`AMMBid`** to place a bid for the auction slot. | ---------- | :-------: | :-------: | :-----------: | | `MaxBidPrice` | | `string` | `STRING NUMBER` | -`MaxBidPrice` represents the maximum price that the bidder wants to pay for the slot. It is specified in units of `LPTokens`. This is not a required field. If specified let `MaxBidPrice` be `X` and let the slot-price computed by price scheduling slgorithm be `Y`, then bidder always pays the min(X, Y). +`MaxBidPrice` represents the maximum price that the bidder wants to pay for the slot. It is specified in units of `LPTokens`. This is not a required field. If specified let `MaxBidPrice` be `X` and let the slot-price computed by price scheduling algorithm be `Y`, then bidder always pays the min(X, Y). --- From 429b2adc249744bc630afb6defcbf665b7c88c05 Mon Sep 17 00:00:00 2001 From: Aanchal Malhotra Date: Tue, 26 Sep 2023 16:40:00 -0400 Subject: [PATCH 07/17] Update README.md --- XLS-30/README.md | 44 ++++++++++++++++++++++++++------------------ 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/XLS-30/README.md b/XLS-30/README.md index 46332973..4135ec84 100644 --- a/XLS-30/README.md +++ b/XLS-30/README.md @@ -116,13 +116,7 @@ Note that in this version, only equal-weighted two asset pools are supported. Ho ##### **`AccountRoot`** ledger entry -A new flag **`lsfAMM`** is introduced to the [**`AccountRoot`**](https://xrpl.org/accountroot.html) object. - -| Flag Name | Hex Value | Description | -| ---------- | :----------------: | :-------:| -| `lsfAMM` | 0x40000000 | If set, it indicates that the object represents an AMM instance| - -Additionally, we introduce a new field called `AMMID` to the `AccountRoot` object. It replaces directory entry to link account root and AMM object. +We introduce a new field called `AMMID` to the `AccountRoot` object. It replaces directory entry to link account root and AMM object. | Field Name | Required? | JSON Type | Internal Type | | ----------------- | :----------------: | :-------: | :-----------: | @@ -149,7 +143,7 @@ The order of the fields to compute the hash is decided canonically. The **`AMMID The **`AMM`** ledger entry contains the following fields for the **`AccountRoot`** object that represents the AMM instance. -1. **`AccountID`** specifies the ID of the `AccountRoot` object associated with this `AMM` ledger entry. +1. **`Account`** specifies the ID of the `AccountRoot` object associated with this `AMM` ledger entry. 2. **`TradingFee`** specifies the fee, in basis point, to be charged to the traders for the trades executed against this AMM instance. Valid values for this field are between 0 and 1000 inclusive. A value of 1 is equivalent to 1/10 bps or 0.001%, allowing trading fee between 0% and 1%. Trading fee is a percentage of the trade size. It is charged on the asset being deposited for the `AMMDeposit` (if applicable) and `Payment` transactions and on the asset being withdrawn for the `AMMWithdraw` (if applicable) transaction. This fee is added to the AMM instance's pools and is distributed to the LPs in proportion to the `LPTokens` upon liquidity removal. 3. **`VoteSlots`** represents an array of `Vote` objects. @@ -157,6 +151,7 @@ The **`AMM`** ledger entry contains the following fields for the **`AccountRoot` 5. **`LPTokenBalance`** specifies the balance of outstanding liquidity Provider Tokens (LPTokens). 6. **`Asset`** specifies the one of the assets of the AMM instance. 7. **`Asset2`** specifies the other asset of the AMM instance. +8. **`OwnerNode`** specifies the page hint for the **DirectoryNode** entry to link the account root and the corresponding AMM objects. Once the AMM **`AccountRoot`** object is created, we make sure that no further transactions can originate from this account. Conceptually, it is an account that is not owned by anyone. So every possible way of signing the transaction for this account MUST be automatically disabled. @@ -222,7 +217,7 @@ ii. is NOT the `issuer` of either token AND the `RequireAuth` flag for the corre If the transaction is successful, -i. Two new ledger entries **`AccountRoot`** and `AMM` are created. +i. Three new ledger entries **`AccountRoot`**, `AMM` and `DirectoryNode` are created. ii. The regular key for the **`AccountRoot`** ledger entry is set to account zero, and the master key is disabled, effectively disabling all possible ways to sign transactions from this account. @@ -259,10 +254,10 @@ Initially by default, $W_{A}$ = $W_{B}$ = 0.5 Unlike other objects in the XRPL, there is no reserve for the `AccountRoot` and `AMM` ledger entries created by an `AMMCreate` transaction. Instead there is a higher `Fee` (~ 1 reserve) for `AMMCreate` transaction in XRP which is burned as a special transaction cost. -### 2.3. `Deleting the AMM instance `AccountRoot` and `AMM` ledger entries` - On final withdraw (i.e. when `LPTokens` balance is 0) the AMM instance automatically deletes up to 512 trust lines. If there are fewer then 512 trustlines then `AMM` object and `AccountRoot` objects are deleted. +### 2.3. `Deleting the AMM instance `AccountRoot`, `AMM` and `DirectoryNode` ledger entries` +On final withdraw (i.e. when `LPTokens` balance is 0) the AMM instance automatically deletes up to 512 trust lines. If there are fewer then 512 trustlines then `AMM`, `AccountRoot` and `DirecotoryNode` objects are deleted. - However, if there are more than 512 trustlines then AMM instance is in empty state (`LPTokens` balance is 0) and we introduce a new transaction type `AMMDelete` to delete the remaining trustlines. . Any one can call `AMMDelete` transaction. `AMMDelete` also has a limit of 512 trustlines and deletes the `AMM` object and `AccountRoot` objects only if there are fewer than 512 trustlines. If there are more trustlines to delete then `AMMDelete` returns `tecINCOMPLETE` code and user should submit `AMMDelete` again. +However, if there are more than 512 trustlines then AMM instance is in empty state (`LPTokens` balance is 0) and we introduce a new transaction type `AMMDelete` to delete the remaining trustlines. Any one can call `AMMDelete` transaction. `AMMDelete` also has a limit of 512 trustlines and deletes the `AMM` object and `AccountRoot` objects only if there are fewer than 512 trustlines. If there are more trustlines to delete then `AMMDelete` returns `tecINCOMPLETE` code and user should submit `AMMDelete` again. In order to avoid destroying assets of the AMM instance, the implementation of the `AMMWithdraw` transaction MUST guarantee that the AMM instance has no asset reserves if no account owns its `LPTokens`. @@ -393,6 +388,14 @@ Note that the relative pricing does not change in case of **all-asset** deposit `LPTokenOut` specifies the amount of shares of the AMM instance pools. +--- + +| Field Name | Required? | JSON Type | Internal Type | +|-------------|:----------------:|:-----------:|:-----------------:| +| `TradingFee` | |`string` | `UINT8` | + +`TradingFee` specifies the trading fee for the AMM instance. This field is only valid if the option flag `tfTwoAssetIfEmpty` is set. In this case, the AMM instance is in the empty state and `AMMDeposit` becomes `AMMCreate` type transaction. + --- Let the following represent the pool composition of AMM instance before trade: @@ -463,7 +466,7 @@ We introduce the following flags to the `AMMDeposit` transaction to identify val | `tfWithdrawAll` | 0x00020000 | If set, it indicates proportional withdrawal of all `LPTokens`| | `tfTwoAssetIfEmpty`| 0x00800000 | If set, it indicates that this deposit can only be submitted on an empty state AMM (LPTokens == 0)| -If `tfTwoAssetIfEmpty` is set, both amounts have to be specified and deposited into AMM as is. It is sort of like `AMMCreate` in an empty AMM state. +If `tfTwoAssetIfEmpty` is set, both amounts have to be specified and deposited into AMM as is. It is sort of like `AMMCreate` in an empty AMM state. Following are the recommended valid combinations. Other invalid combinations may result in the failure of transaction. @@ -471,7 +474,8 @@ If `tfTwoAssetIfEmpty` is set, both amounts have to be specified and deposited - `Amount`, `[LPTokenOut]` - `Amount` , `Amount2`, `[LPTokenOut]` - `Amount` and `LPTokenOut` -- `Amount` and `EPrice` +- `Amount` and `EPrice` +- `Amount` , `Amount2`, `[TradingFee]` Details for above combinations: @@ -488,7 +492,7 @@ If the asset to be deposited is a token, specifying the `value` field is require `LPTokenOut`, if included, specified minimum `LPTokens` amount that the user receives, else the transaction will fail. -3. Fields specified: `Amount`, `Amount2`, `[LPTokenOut]` and Flag: `tfTwoAsset` +3. Fields specified: `Amount`, `Amount2`, `[LPTokenOut]`, and Flag: `tfTwoAsset` Such a transaction assumes proportional deposit of pool assets with the constraints on the maximum amount of each asset that the trader is willing to deposit. @@ -506,7 +510,10 @@ a. amount of asset1 if specified in `Amount` specifies the maximum amount of ass b. The effective-price of the `LPTokenOut` traded out does not exceed the specified `EPrice` - +6. Fields specified: `Amount`, `Amount2`, `[TradingFee]` and Flag: `tfTwoAssetIfEmpty` + +Such a transaction assumes proportional deposit of pool assets in the empty state. + Following updates after a successful `AMMDeposit` transaction: - The deposited asset, if XRP, is transferred from the account that initiated the transaction to the AMM instance account, thus changing the `Balance` field of each account @@ -988,7 +995,7 @@ We introduce a new object field `AuctionSlot` in the **`AMM`** object associated | ---------- | :-------: | :-------: | :-----------: | | `DiscountedFee` | :heavy_check_mark: | `string` | `UINT32` | -`DiscountedFee` represents the `TradingFee` to be charged to this account for trading against the AMM instance. By default it is 0. +`DiscountedFee` represents the `TradingFee` to be charged to this account for trading against the AMM instance. By default it is `TradingFee`/10. --- @@ -1076,6 +1083,7 @@ The proposal allows for traders to specify different combinations of the fields - `Amount` , `Amount2`, `[LPTokenOut]` - `Amount` and `LPTokenOut` - `Amount` and `EPrice` +- `Amount` , `Amount2`, `[TradingFee]` Implementation details for above combinations: @@ -1150,7 +1158,7 @@ b. The effective-price of the `LPToken` traded out does not exceed the specified - The amount of asset1 in. Let this be `Q` - The amount of `LPTokenOut` out. Let this be `W` - The amount of asset1 to be deposited is `Q` - - The amount of `LPTokenOut` to be issued is `W` + - The amount of `LPTokenOut` to be issued is `W` Following updates after a successful **`AMMDeposit`** transaction: From d91011ffa007f2cecce316876d5e7f8e5f9a7643 Mon Sep 17 00:00:00 2001 From: Aanchal Malhotra Date: Tue, 26 Sep 2023 17:46:58 -0400 Subject: [PATCH 08/17] Update README.md --- XLS-30/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/XLS-30/README.md b/XLS-30/README.md index 4135ec84..8fb134b1 100644 --- a/XLS-30/README.md +++ b/XLS-30/README.md @@ -116,7 +116,7 @@ Note that in this version, only equal-weighted two asset pools are supported. Ho ##### **`AccountRoot`** ledger entry -We introduce a new field called `AMMID` to the `AccountRoot` object. It replaces directory entry to link account root and AMM object. +We introduce a new field called `AMMID` to the `AccountRoot` object. It provides an easy link to the corresponding `AMM` object and a way to identify the AMM `AccountRoot`. | Field Name | Required? | JSON Type | Internal Type | | ----------------- | :----------------: | :-------: | :-----------: | @@ -257,7 +257,7 @@ Unlike other objects in the XRPL, there is no reserve for the `AccountRoot` and ### 2.3. `Deleting the AMM instance `AccountRoot`, `AMM` and `DirectoryNode` ledger entries` On final withdraw (i.e. when `LPTokens` balance is 0) the AMM instance automatically deletes up to 512 trust lines. If there are fewer then 512 trustlines then `AMM`, `AccountRoot` and `DirecotoryNode` objects are deleted. -However, if there are more than 512 trustlines then AMM instance is in empty state (`LPTokens` balance is 0) and we introduce a new transaction type `AMMDelete` to delete the remaining trustlines. Any one can call `AMMDelete` transaction. `AMMDelete` also has a limit of 512 trustlines and deletes the `AMM` object and `AccountRoot` objects only if there are fewer than 512 trustlines. If there are more trustlines to delete then `AMMDelete` returns `tecINCOMPLETE` code and user should submit `AMMDelete` again. +However, if there are more than 512 trustlines then AMM instance is in empty state (`LPTokens` balance is 0) and we introduce a new transaction type `AMMDelete` to delete the remaining trustlines. Any one can call `AMMDelete` transaction. `AMMDelete` also has a limit of 512 trustlines and deletes the `AMM`, `AccountRoot` and `DirectoryNode` objects only if there are fewer than 512 trustlines. If there are more trustlines to delete then `AMMDelete` returns `tecINCOMPLETE` code and user should submit `AMMDelete` again. In order to avoid destroying assets of the AMM instance, the implementation of the `AMMWithdraw` transaction MUST guarantee that the AMM instance has no asset reserves if no account owns its `LPTokens`. From 541824328658411fe2594d5971d8507784d01a3f Mon Sep 17 00:00:00 2001 From: Aanchal Malhotra Date: Thu, 28 Sep 2023 13:37:03 -0400 Subject: [PATCH 09/17] Update XLS-30/README.md Co-authored-by: Elliot Lee --- XLS-30/README.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/XLS-30/README.md b/XLS-30/README.md index 8fb134b1..d6e75f71 100644 --- a/XLS-30/README.md +++ b/XLS-30/README.md @@ -1259,4 +1259,9 @@ Following updates after a successful **`AMMWithdraw`** transaction: - The pool composition is updated. Conservation function is not preserved in case of liquidity withdrawal (and is not expected to.) ## Implementation -A proposed reference implementation is in progress here: https://github.com/XRPLF/rippled/pull/4294 +The reference implementation of this spec can be found in `rippled`: + +- https://github.com/XRPLF/rippled/pull/4294 +- https://github.com/XRPLF/rippled/pull/4626 +- https://github.com/XRPLF/rippled/pull/4674 +- https://github.com/XRPLF/rippled/pull/4682 From ef5df65d710ffcc30e65b6f8a0a1d2e30a826539 Mon Sep 17 00:00:00 2001 From: Aanchal Malhotra Date: Thu, 28 Sep 2023 13:38:08 -0400 Subject: [PATCH 10/17] Update XLS-30/README.md Co-authored-by: Elliot Lee --- XLS-30/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/XLS-30/README.md b/XLS-30/README.md index d6e75f71..695fe2f1 100644 --- a/XLS-30/README.md +++ b/XLS-30/README.md @@ -257,7 +257,7 @@ Unlike other objects in the XRPL, there is no reserve for the `AccountRoot` and ### 2.3. `Deleting the AMM instance `AccountRoot`, `AMM` and `DirectoryNode` ledger entries` On final withdraw (i.e. when `LPTokens` balance is 0) the AMM instance automatically deletes up to 512 trust lines. If there are fewer then 512 trustlines then `AMM`, `AccountRoot` and `DirecotoryNode` objects are deleted. -However, if there are more than 512 trustlines then AMM instance is in empty state (`LPTokens` balance is 0) and we introduce a new transaction type `AMMDelete` to delete the remaining trustlines. Any one can call `AMMDelete` transaction. `AMMDelete` also has a limit of 512 trustlines and deletes the `AMM`, `AccountRoot` and `DirectoryNode` objects only if there are fewer than 512 trustlines. If there are more trustlines to delete then `AMMDelete` returns `tecINCOMPLETE` code and user should submit `AMMDelete` again. +However, if there are more than 512 trustlines then AMM instance remains in empty state (`LPTokens` balance is 0). To handle cleaning this up, we introduce a new transaction type `AMMDelete` to delete the remaining trustlines. Anyone can call the `AMMDelete` transactor. `AMMDelete` also has a limit of 512 trustlines and deletes the `AMM`, `AccountRoot` and `DirectoryNode` objects only if there are fewer than 512 trustlines at the time it executes. If there are more trustlines to delete, then `AMMDelete` returns the `tecINCOMPLETE` result code and the user should submit another `AMMDelete` to delete more entries. In order to avoid destroying assets of the AMM instance, the implementation of the `AMMWithdraw` transaction MUST guarantee that the AMM instance has no asset reserves if no account owns its `LPTokens`. From 6c78a1d34dad273c98484563ffe356df650fc084 Mon Sep 17 00:00:00 2001 From: Aanchal Malhotra Date: Thu, 28 Sep 2023 13:38:36 -0400 Subject: [PATCH 11/17] Update XLS-30/README.md Co-authored-by: Elliot Lee --- XLS-30/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/XLS-30/README.md b/XLS-30/README.md index 695fe2f1..49a497d4 100644 --- a/XLS-30/README.md +++ b/XLS-30/README.md @@ -254,7 +254,7 @@ Initially by default, $W_{A}$ = $W_{B}$ = 0.5 Unlike other objects in the XRPL, there is no reserve for the `AccountRoot` and `AMM` ledger entries created by an `AMMCreate` transaction. Instead there is a higher `Fee` (~ 1 reserve) for `AMMCreate` transaction in XRP which is burned as a special transaction cost. -### 2.3. `Deleting the AMM instance `AccountRoot`, `AMM` and `DirectoryNode` ledger entries` +### 2.3. Deleting the AMM instance `AccountRoot`, `AMM` and `DirectoryNode` ledger entries On final withdraw (i.e. when `LPTokens` balance is 0) the AMM instance automatically deletes up to 512 trust lines. If there are fewer then 512 trustlines then `AMM`, `AccountRoot` and `DirecotoryNode` objects are deleted. However, if there are more than 512 trustlines then AMM instance remains in empty state (`LPTokens` balance is 0). To handle cleaning this up, we introduce a new transaction type `AMMDelete` to delete the remaining trustlines. Anyone can call the `AMMDelete` transactor. `AMMDelete` also has a limit of 512 trustlines and deletes the `AMM`, `AccountRoot` and `DirectoryNode` objects only if there are fewer than 512 trustlines at the time it executes. If there are more trustlines to delete, then `AMMDelete` returns the `tecINCOMPLETE` result code and the user should submit another `AMMDelete` to delete more entries. From 502eb33120ca7fec90eb57f42a056f66654e50f2 Mon Sep 17 00:00:00 2001 From: Aanchal Malhotra Date: Thu, 28 Sep 2023 17:43:20 -0400 Subject: [PATCH 12/17] XLS-40 --- XLS-40.md | 416 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 416 insertions(+) create mode 100644 XLS-40.md diff --git a/XLS-40.md b/XLS-40.md new file mode 100644 index 00000000..039a5200 --- /dev/null +++ b/XLS-40.md @@ -0,0 +1,416 @@ +
    
+Title:        Decentralized Identity on XRP Ledger
+Revision:     1 (2023-09-28)
+
+
Author: Aanchal Malhotra +Affiliation: Ripple + +
+ +# 1. Abstract +Self-sovereign identity, defined as a lifetime portable digital identity that does not depend on any centralized authority, requires a new class of identifier that fulfills the following four requirements: persistence, global resolvability, cryptographic verifiability, and decentralization. [World Wide Web Consortium](https://www.w3.org/2022/07/pressrelease-did-rec.html.en) (W3C) standardized Decentralized Identifiers (DIDs) are a new type of identifier that enable verifiable, self-sovereign digital identity and are designed to be compatible with any distributed ledger or network. In the context of digital identities, W3C's standards for DIDs and Verifiable Credentials (VCs) are rapidly gaining traction, especially in blockchain-related domains. In this document we propose to implement native support for W3C DIDs on XRP Ledger. + +To this end, we specify the following on XRPL: +- A new `DID method` that describes: + - The format for XRP ledger DID, and + - Defines how XRP ledger DIDs are generated +- How to do `CRUD operations` on XRP ledger DIDs + +This specification conforms to the requirements specified in the [DID v1.0](https://www.w3.org/TR/did-core/) specification currently recommended by the W3C Credentials Community Group. + +# 2. Principles & Goals +## 2.1. Principles + +This proposal chooses to recommend W3C DID identity standard to satisfy the following first principles: + +- **Decentralized:** Requires no central issuing agency and functions effectively in Decentralized Finance. + +- **Persistent and Portable:** Inherently persistent and long-lived, not requiring the continued operation of any underlying organization and portable between different applications. + +- **Cryptographically Verifiable:** Based on cryptographic proofs rather than out-of-band trust. + +- **Universally Resolvable and Interoperable:** Open to any solution that recognizes the common W3C DID standards and requires no one specific software vendor implementation. + + +## 2.2. Goals & Non-Goals + +- This document aims to define DID identifier format for XRP ledger conformant to W3C DID standards that can be created and owned by any XRPL account holder, and specify definitions for DID methods to create, read, update and delete DID (data) that can be implemented by any service, wallet, or application. + +- This proposal is NOT intended as a competing decentralized identity standard; it aims to leverage existing (and emerging) decentralized identity standard proposed by W3C. + +- The proposal is motivated to enable **individual users** to create, and manage their decentralized identifiers while having complete control over the private keys and contents of the identity object. + +# 3. New On-Ledger Objects and Transactions +We propose one new ledger object and two new transaction types. +- **DID** is a new ledger object that is unique to an XRPL account and may contain a reference to, or the hash of, or the [W3C DID document](https://w3c-ccg.github.io/did-primer/#did-documents) itself associated with the corresponding DID. +- **DIDSet** is a new transaction type used to perform the following two operations: + - `Create` the new ledger object `DID` with `URI`, and/or `Data` fields, thus adding the required reserve towards the account that initiated the transaction. + - `Update` the mutable `URI` and `Data` fields of the `DID` object. +- **DIDDelete** is a new transaction type used to delete the `DID` object, thus reducing the reserve requirement towards the account that created the object. + +# 4. XRPL Decentralized Identifier (DID) Specification +In this section we specify the implementation details of W3C DID standard that are specific to XRP Ledger. + +## 4.1. The `DID` Object +We propose a new ledger object called **`DID`** that holds references to or data associated with a single DID. The `DID` object is created and updated using the `DIDSet` transaction and is deleted using the `DIDDelete` transaction. + +### 4.1.1. Object Fields +`DID` object may have the following required and optional fields. + +| Field Name | Required? | JSON Type | Internal Type +| ----------------- | :----------------: | :-------: | :-----------: +| `LedgerEntryType` | :heavy_check_mark: | `string` | `UINT16` | + +Identifies the type of ledger object. The proposal recommends the value `0x0049` as the reserved entry type. + +--- +| Field Name | Required? | JSON Type | Internal Type +| ----------------- | :----------------: | :-------: | :-----------: +| `PreviousTxnID` | :heavy_check_mark: | `string` | `Hash256` | + +The identifying hash of the transaction that most recently modified this object. + +--- +| Field Name | Required? | JSON Type | Internal Type +| ----------------- | :----------------: | :-------: | :-----------: +| `PreviousTxnLgrSeq` | :heavy_check_mark: | `number` | `UINT32` | + +The index of the ledger that contains the transaction that most recently modified this object. + +--- + + +| Field Name | Required? | JSON Type | Internal Type +| ----------------- | :----------------: | :-------: | :-----------: +| `URI` | | `string` | `BLOB` | + +`URI` specifies a Universal Resource Identifier, a.k.a. URI that SHOULD point to the corresponding DID document or to the data associated with the DID. This field could be an HTTP(S) URL or IPFS URI. The `URI` field is NOT checked for validity, but the field is limited to a maximum length of 256 bytes. + +--- +| Field Name | Required? | JSON Type | Internal Type +| -------------| :----------------: | :-------: | :-----------: +| `Data` | | `string` | `BLOB` | + +`Data` field SHOULD contain the public attestations of identity credentials associated with the DID. The `Data` field is NOT checked for validity, but the field is limited to a maximum length of 256 bytes. + +--- +| Field Name | Required? | JSON Type | Internal Type +| -------------| :----------------: | :-------: | :-----------: +| `DIDDocument` | | `string` | `BLOB` | + +`DIDDocument` field SHOULD contain the DID document per W3C standards associated with the DID. The field is NOT checked for validity, and is limited to a maximum length of 256 bytes. + +Note: +- Either `URI`, `Data` or `DIDDocument` field MUST be present to create and update the `DID` object. +- All `URI`, `Data` and `DIDDocument` fields MUST be absent to delete the `DID` object. + + +### 4.1.2. The `DID` Object ID Format +`DID` object may contain public data associated with the XRPL account's identity. This requires the `DID` to be: +- Unique in the XRPL namespace, and +- Uniquely associated with the XRPL account. + +We compute the `DID` object ID, a.k.a., `DIDID` as the `SHA-512Half` of the following values, concatenated in order: + +- The `DID` space key (`0x0049`) +- The Account ID + +### 4.1.3. Reserve Requirements +The account that creates the `DID` object will incur one owner reserve ~2 XRP at the time of writing this document. + +## 4.2. XRP Ledger DID Method Specification +In this section, we describe the DID method specification that conforms to the requirements specified in the DID specification currently published by the W3C Credentials Community Group. For more information about DIDs and DID method specifications, refer to the DID [Primer](https://github.com/WebOfTrustInfo/rwot5-boston/blob/master/topics-and-advance-readings/did-primer.md). + +### 4.2.1. XRP Ledger DID Scheme +The DID format as defined by W3C is as follows: +``` +"did:" method-name ":" method-specific-idstring +``` +We propose the following format for DIDs on XRPL: +``` +"did:xrpl": network-id: xrpl-specific-idstring +``` + +The components specific to the XRPL network are the following: + +- `method-name`: The `"xrpl"` namestring specifies that this is a DID for XRP Ledger. +A DID that uses this method MUST begin with the following prefix: `did:xrpl`. Per the DID specification, this string MUST be in lowercase. The remainder of the DID, after the prefix, is specified below. + +- `method-specific-idstring` is formed by `network-id` and `xrpl-specific-idstring` + + - `network-id`: `network-id` is a chain ID which is an identifier of XRP ledger networks. It specifies the underlying network instance where the `DID` is stored. Per [XLS-37d specification](https://github.com/XRPLF/rippled/pull/4418), in XRPL Protocol Chains the Network ID should match the chosen peer port. + + - `xrpl-specific-idstring` is generated as described in the next section. + + +### 4.2.2. XRPL-specific-idstring Generation Method +XRPL DID MUST be unique within the XRPL network. + +`xrpl-specific-idstring` is the `AccountID` or the hex of `master public key` of the `DID` object's account. See [this](https://xrpl.org/accounts.html#address-encoding) for more details on XRPL public keys. + +Example: +A valid DID for an XRPL network may be +``` +did:xrpl:1:rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh +``` +or +``` +did:xrpl:1:0330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD020 +``` +The above DIDs are case-insensitive and will resolve to the same `DID` object. + +# 5. CRUD Operations +In this section we outline the following four CRUD operations for ``did:xrpl`` method. +- `Create` +- `Read` +- `Update` +- `Delete` + +## 5.1. DIDSet Transaction +The proposal introduces a new transaction type: **`DIDSet`** that can be used to: +- `Create` a new `DID` object, +- `Update` the existing `DID` object. + +### 5.1.1 Example **`DIDSet`** JSON +``` +{ + "TransactionType": "DIDSet", + "Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", + "Fee": "10", + "Sequence": 391, + "URI": "ipfs://bafybeigdyrzt5sfp7udm7hu76uh7y26nf4dfuylqabf3oclgtqy55fbzdi", + "Data": , + "SigningPubKey":"0330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD020", + ... + + } +``` +## Create +If the `DID` object associated with the `Account` does not exist, + - If both `URI` and `Data` fields are not present in the transaction, then transaction fails. + - Otherwise, a successful `DIDSet` transaction creates a new `DID` object with the following object ID: + + `SHA-512Half` of the following values, concatenated in order: + + - The `DID` space key (`0x0049`) + - The Account ID of the `Account`, i.e. rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh + +#### DID associated with this object is: +``` +did:xrpl:1:rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh +``` +or + +``` +did:xrpl:1:0330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD020 +``` + +### Implicit DID document +Some minimalistic use cases might only need signatures and simple authorization tokens, but don't need support for multiple keys or devices, complex organizational hierarchies and other advanced rights management features. + +To lower the entry level, we do not always require registering a `DID` by publishing a reference to or the DID Document on the ledger. If there's no explicitly registered `DID` found on the ledger then an implicit document is used instead as a default. Any update on this implicit document requires registering the `DID` object and applied changes on the ledger to be valid. + +For example, the implicit DID Document of `did:xrpl:1:0330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD020` enables only a single key 0330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD020 to authorize changes on the DID document or sign credentials in the name of the DID. + +## Update +If the `DID` object associated with the `Account` exists, + - If `URI`, `Data` and `DIDDocument` fields are not present, then transaction fails. + - Otherwise, a successful `DIDSet` transaction updates this object. + +### 5.1.2. Transaction-specific fields +| Field Name | Required? | JSON Type | Internal Type +| ---------------- |:-----------------: | :-------: | :---------------: +| `TransactionType`|:heavy_check_mark: | `string` | `UINT16` | + +Indicates the new transaction type **`DIDSet`**. The integer value is 40. + +--- +| Field Name | Required? | JSON Type | Internal Type +| ---------------- |:-----------------: | :-------: | :---------------: +| `Account` |:heavy_check_mark: | `string` | `AccountID` | + +Indicates the account which initiates the `DIDSet` transaction. This account MUST be a funded account on ledger. + +--- +| Field Name | Required? | JSON Type | Internal Type | +| --------------------- | :-----------------: | :-------: | :-------------: | +| `Fee` | :heavy_check_mark: | `number` | `Amount` | + +Indicates the fee that the account submitting this transaction is willing to pay. + +--- +| Field Name | Required? | JSON Type | Internal Type | +| -----------| :-----------------: | :-------: | :-------------: | +| `URI` | | `string` | `BLOB` | + +Indicates the `URI` field for this object. + +--- +| Field Name | Required? | JSON Type | Internal Type | +| -----------| :-----------------: | :-------: | :-------------: | +| `Data` | | `string` | `BLOB` | + +Indicates the `Data` field for this object. + +--- + +| Field Name | Required? | JSON Type | Internal Type +| -------------| :----------------: | :-------: | :-----------: +| `DIDDocument` | | `string` | `BLOB` | + +Indicates the DID document for this object. + +:notebook: If the `URI`, `Data`, or `DIDDocument` fields are missing, they will remain unchanged. However, if they contain an empty string, they will be deleted, otherwise, they will be updated. + +## 5.2. Read + +The initial step in utilizing a DID for an application may involve resolving the DID to access the underlying DID Document or attestations. This resolution process unveils the cryptographic material and service endpoints linked to the specific DID. + +In the case of XRPL DID, the `read` operation facilitates the resolution to the associated `DID` object. Upon successful resolution, applications can retrieve and utilize the relevant `URI` and/or `Data`, and/or `DIDDocument` fields contained within the `DID` object: + +Given the input DID for an account, follow these steps: + +- Retrieve the xrpl-specific-idstring of the DID. + +- If the xrpl-specific-idstring represents a public key: + + - Compute the Account ID using the method described [here](https://xrpl.org/accounts.html#address-encoding). + +- Retrieve the contents of the corresponding `DID` object in its raw format using the XRPL's [`account_objects`]( https://xrpl.org/account_objects.html#) command. Use the `account` field to specify the Account ID to retrieve all objects owned by that account, including `DID` object in the raw ledger format. Or optionally use the `type` field to filter the results by `ledger_entry` type, i.e. `DID` to retrieve the contents of just the `DID` object. + +### Example +Given the DID **did:xrpl:1:rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn**, do the following: +- Retrieve `rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn` +- Perform the `account_objects` method request to retrieve the contents of `DID` object: +``` +{ + "method": "account_objects", + "params": [ + { + "account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", + "ledger_index": "validated", + "type": "DID" + } + ] +} +``` + +A sample response to the above query might look like this: + +``` +200 OK +{ + "result": { + "account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", + "account_objects": [ + { + "URI":"ipfs://bafybeigdyrzt5sfp7udm7hu76uh7y26nf4dfuylqabf3oclgtqy55fbzdi" + } + ], + "validated": true + } +} + +``` +Upon receiving this response, an IPFS address (CAS) can be retrieved from the `URI` field. This address can then be resolved to retrieve the corresponding DID Document. + +:notebook: It is recommended that the applications implementing this method extend it to enable DID document fetching from the retrieved URI. + +Alternatively, one can use the [`ledger_entry`](https://xrpl.org/ledger_entry.html#ledger_entry) method to retrieve a single ledger entry (in this case `DID`) from the XRP Ledger in its raw format. + +## 5.3. DIDDelete Transaction +XRP ledger `DID` object owner or controller MAY want to delete the object. For this, we introduce a new transaction type called **`DIDDelete`**. A successful transaction will remove the ledger object and reduce the reserve requirement of the owner account. + +### 5.3.1. Example **`DIDDelete`** JSON +``` +{ + "TransactionType": "DIDDelete", + "Account": "rp4pqYgrTAtdPHuZd1ZQWxrzx45jxYcZex", + "Fee": "12", + "Sequence": 391, + "SigningPubKey":"0293A815C095DBA82FAC597A6BB9D338674DB93168156D84D18417AD509FFF5904", + "TxnSignature":"3044022011E9A7EE3C7AE9D202848390522E6840F7F3ED098CD13E...", + ... +} +``` +A successful `DIDDelete` transaction deletes the `DID` object corresponding to the `Account` + +### 5.3.2. Transaction-Specific Fields + +| Field Name | Required? | JSON Type | Internal Type +| ---------------- |:-----------------: | :-------: | :---------------: +| `TransactionType`|:heavy_check_mark: | `string` | `UINT16` | + +Indicates the new transaction type **`DIDDelete`**. The integer value is 41. + +--- +| Field Name | Required? | JSON Type | Internal Type | +| -----------| :-----------------: | :-------: | :-------------: | +| `Account` | :heavy_check_mark: | `string` | `AccountID` | + +Indicates the account that initiated the transaction. + +--- +| Field Name | Required? | JSON Type | Internal Type | +| -----------| :-----------------: | :-------: | :-------------: | +| `Fee` | :heavy_check_mark: | `string` | `Amount` | + +Indicates the fee that the account is willing to pay for this transaction. + + + +# 6. Privacy and Security Considerations +There are several security and privacy considerations that implementers would want to take into consideration when implementing this specification. + +## 6.1. Key Management + +The entity which controls the private key associated with the `DID` object, i.e. the XRPL `Account` also effectively controls the reference to the DID Document which the DID resolves to. Thus great care should be taken to ensure that the private key is kept private. Methods for ensuring key privacy are outside the scope of this document. + + +## 6.2. DID Document Public Profile +The DID document or other data associated with the XRPL DID's `URI` and/or `Data`, and/or `DIDDocument` fields can contain any content, though it is recommended that it conforms to the W3C DID Document and Verifiable Credentials (VC) specification. As anchored DIDs on XRPL can be resolved by anyone, care should be taken to only update to resolve DID Documents and data which DO NOT expose any sensitive personal information, or information which one may not wish to be public. DID documents should be limited to verification methods and service endpoints, and SHOULD not store any personal information. + +## 6.3. IPFS and Canonicity +IPFS allows anyone to store content publicly on the nodes in a distributed network. A common misconception is that anyone can edit content, however the content-addressability of IPFS means that this new edited content will have a different address to the original. While any entity can copy a DID Document anchored with an XRPL account's `URI`, they cannot change the document that a DID resolves to via the XRPL `account_objects` resolution unless they control the private key which created the corresponding `DID` object. + +For more, see [§ 10. Privacy Considerations](https://www.w3.org/TR/did-core/#privacy-considerations) in did-core. + +# 7. Reference Implementations +TBD + +# 8. Appendices +## Appendix 1. DID Document + +A DID is associated with a DID document. A DID document contains the necessary information to cryptographically verify the identity of the DID subject. W3C defines the [core properties](https://www.w3.org/TR/did-core/#core-properties) in a DID document, that describe relationships between the DID subject and the value of the property. For example, a DID document could contain cryptographic public keys such that the DID subject can use it to authenticate itself and proves its association with the DID. Usually, a DID document can be serialized to JSON representation or JSON-LD representation (see [DIDs v1.0]). + +Applications may choose one of the following for the DID document associated with a DID: +- Store a reference on the ledger in the `URI` field of `DID` object to the DID document stored in one or more parts on other decentralized storage networks such as IPFS or STORJ. +- Store a minimal DID document in the `Data` field of the `DID` object. +- Specify a minimal implicit DID document generated from the DID and other available public information. + +While not normative, a sample XRPL DID Document MAY look like: +``` +{ + "@context" : "https://w3id.org/did/v1", + "id" : "did:xrpl:1:rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", + "publicKey" : [ + { + "id" : "did:xrpl:1:rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn #keys-1", + "type" : ["CryptographicKey", "EcdsaKoblitzPublicKey"], + "curve" : "secp256k1", + "expires" : 15674657, + "publicKeyHex": "04f42987b7faee8b95e2c3a3345224f00e00dfc67ba882…." + } ] +} +``` + + W3C defines the [core properties](https://www.w3.org/TR/did-core/#core-properties) in a DID document, that describe relationships between the DID subject and the value of the property. + + +## Appendix 2. Universal Resolver +A Universal Resolver is an identifier resolver that works with any decentralized identifier system, including W3C DIDs. Refer [here](https://github.com/decentralized-identity/universal-resolver). A driver for XRPL DID method resolution will be added to universal resolver configurations to make it publicly accessible. + +## Appendix 3. Frequently Asked Questions +Q: Why use "Data" as the field name instead of a more specific term? + +A: The term "Data" was chosen to maintain flexibility and inclusivity within the specification. While some issuers refer to this information as "Attestations," others may use alternative terminology such as "public validations" or other terms. By using the term "Data," we aim to ensure that the specification remains adaptable to various implementations and promotes interoperability and broader applicability across the ecosystem of decentralized identity systems. \ No newline at end of file From 42ecb7ebfb4e028907699054fa8075123b73ce36 Mon Sep 17 00:00:00 2001 From: Aanchal Malhotra Date: Thu, 28 Sep 2023 17:44:47 -0400 Subject: [PATCH 13/17] Delete XLS-40.md --- XLS-40.md | 416 ------------------------------------------------------ 1 file changed, 416 deletions(-) delete mode 100644 XLS-40.md diff --git a/XLS-40.md b/XLS-40.md deleted file mode 100644 index 039a5200..00000000 --- a/XLS-40.md +++ /dev/null @@ -1,416 +0,0 @@ -
    
-Title:        Decentralized Identity on XRP Ledger
-Revision:     1 (2023-09-28)
-
-
Author: Aanchal Malhotra -Affiliation: Ripple - -
- -# 1. Abstract -Self-sovereign identity, defined as a lifetime portable digital identity that does not depend on any centralized authority, requires a new class of identifier that fulfills the following four requirements: persistence, global resolvability, cryptographic verifiability, and decentralization. [World Wide Web Consortium](https://www.w3.org/2022/07/pressrelease-did-rec.html.en) (W3C) standardized Decentralized Identifiers (DIDs) are a new type of identifier that enable verifiable, self-sovereign digital identity and are designed to be compatible with any distributed ledger or network. In the context of digital identities, W3C's standards for DIDs and Verifiable Credentials (VCs) are rapidly gaining traction, especially in blockchain-related domains. In this document we propose to implement native support for W3C DIDs on XRP Ledger. - -To this end, we specify the following on XRPL: -- A new `DID method` that describes: - - The format for XRP ledger DID, and - - Defines how XRP ledger DIDs are generated -- How to do `CRUD operations` on XRP ledger DIDs - -This specification conforms to the requirements specified in the [DID v1.0](https://www.w3.org/TR/did-core/) specification currently recommended by the W3C Credentials Community Group. - -# 2. Principles & Goals -## 2.1. Principles - -This proposal chooses to recommend W3C DID identity standard to satisfy the following first principles: - -- **Decentralized:** Requires no central issuing agency and functions effectively in Decentralized Finance. - -- **Persistent and Portable:** Inherently persistent and long-lived, not requiring the continued operation of any underlying organization and portable between different applications. - -- **Cryptographically Verifiable:** Based on cryptographic proofs rather than out-of-band trust. - -- **Universally Resolvable and Interoperable:** Open to any solution that recognizes the common W3C DID standards and requires no one specific software vendor implementation. - - -## 2.2. Goals & Non-Goals - -- This document aims to define DID identifier format for XRP ledger conformant to W3C DID standards that can be created and owned by any XRPL account holder, and specify definitions for DID methods to create, read, update and delete DID (data) that can be implemented by any service, wallet, or application. - -- This proposal is NOT intended as a competing decentralized identity standard; it aims to leverage existing (and emerging) decentralized identity standard proposed by W3C. - -- The proposal is motivated to enable **individual users** to create, and manage their decentralized identifiers while having complete control over the private keys and contents of the identity object. - -# 3. New On-Ledger Objects and Transactions -We propose one new ledger object and two new transaction types. -- **DID** is a new ledger object that is unique to an XRPL account and may contain a reference to, or the hash of, or the [W3C DID document](https://w3c-ccg.github.io/did-primer/#did-documents) itself associated with the corresponding DID. -- **DIDSet** is a new transaction type used to perform the following two operations: - - `Create` the new ledger object `DID` with `URI`, and/or `Data` fields, thus adding the required reserve towards the account that initiated the transaction. - - `Update` the mutable `URI` and `Data` fields of the `DID` object. -- **DIDDelete** is a new transaction type used to delete the `DID` object, thus reducing the reserve requirement towards the account that created the object. - -# 4. XRPL Decentralized Identifier (DID) Specification -In this section we specify the implementation details of W3C DID standard that are specific to XRP Ledger. - -## 4.1. The `DID` Object -We propose a new ledger object called **`DID`** that holds references to or data associated with a single DID. The `DID` object is created and updated using the `DIDSet` transaction and is deleted using the `DIDDelete` transaction. - -### 4.1.1. Object Fields -`DID` object may have the following required and optional fields. - -| Field Name | Required? | JSON Type | Internal Type -| ----------------- | :----------------: | :-------: | :-----------: -| `LedgerEntryType` | :heavy_check_mark: | `string` | `UINT16` | - -Identifies the type of ledger object. The proposal recommends the value `0x0049` as the reserved entry type. - ---- -| Field Name | Required? | JSON Type | Internal Type -| ----------------- | :----------------: | :-------: | :-----------: -| `PreviousTxnID` | :heavy_check_mark: | `string` | `Hash256` | - -The identifying hash of the transaction that most recently modified this object. - ---- -| Field Name | Required? | JSON Type | Internal Type -| ----------------- | :----------------: | :-------: | :-----------: -| `PreviousTxnLgrSeq` | :heavy_check_mark: | `number` | `UINT32` | - -The index of the ledger that contains the transaction that most recently modified this object. - ---- - - -| Field Name | Required? | JSON Type | Internal Type -| ----------------- | :----------------: | :-------: | :-----------: -| `URI` | | `string` | `BLOB` | - -`URI` specifies a Universal Resource Identifier, a.k.a. URI that SHOULD point to the corresponding DID document or to the data associated with the DID. This field could be an HTTP(S) URL or IPFS URI. The `URI` field is NOT checked for validity, but the field is limited to a maximum length of 256 bytes. - ---- -| Field Name | Required? | JSON Type | Internal Type -| -------------| :----------------: | :-------: | :-----------: -| `Data` | | `string` | `BLOB` | - -`Data` field SHOULD contain the public attestations of identity credentials associated with the DID. The `Data` field is NOT checked for validity, but the field is limited to a maximum length of 256 bytes. - ---- -| Field Name | Required? | JSON Type | Internal Type -| -------------| :----------------: | :-------: | :-----------: -| `DIDDocument` | | `string` | `BLOB` | - -`DIDDocument` field SHOULD contain the DID document per W3C standards associated with the DID. The field is NOT checked for validity, and is limited to a maximum length of 256 bytes. - -Note: -- Either `URI`, `Data` or `DIDDocument` field MUST be present to create and update the `DID` object. -- All `URI`, `Data` and `DIDDocument` fields MUST be absent to delete the `DID` object. - - -### 4.1.2. The `DID` Object ID Format -`DID` object may contain public data associated with the XRPL account's identity. This requires the `DID` to be: -- Unique in the XRPL namespace, and -- Uniquely associated with the XRPL account. - -We compute the `DID` object ID, a.k.a., `DIDID` as the `SHA-512Half` of the following values, concatenated in order: - -- The `DID` space key (`0x0049`) -- The Account ID - -### 4.1.3. Reserve Requirements -The account that creates the `DID` object will incur one owner reserve ~2 XRP at the time of writing this document. - -## 4.2. XRP Ledger DID Method Specification -In this section, we describe the DID method specification that conforms to the requirements specified in the DID specification currently published by the W3C Credentials Community Group. For more information about DIDs and DID method specifications, refer to the DID [Primer](https://github.com/WebOfTrustInfo/rwot5-boston/blob/master/topics-and-advance-readings/did-primer.md). - -### 4.2.1. XRP Ledger DID Scheme -The DID format as defined by W3C is as follows: -``` -"did:" method-name ":" method-specific-idstring -``` -We propose the following format for DIDs on XRPL: -``` -"did:xrpl": network-id: xrpl-specific-idstring -``` - -The components specific to the XRPL network are the following: - -- `method-name`: The `"xrpl"` namestring specifies that this is a DID for XRP Ledger. -A DID that uses this method MUST begin with the following prefix: `did:xrpl`. Per the DID specification, this string MUST be in lowercase. The remainder of the DID, after the prefix, is specified below. - -- `method-specific-idstring` is formed by `network-id` and `xrpl-specific-idstring` - - - `network-id`: `network-id` is a chain ID which is an identifier of XRP ledger networks. It specifies the underlying network instance where the `DID` is stored. Per [XLS-37d specification](https://github.com/XRPLF/rippled/pull/4418), in XRPL Protocol Chains the Network ID should match the chosen peer port. - - - `xrpl-specific-idstring` is generated as described in the next section. - - -### 4.2.2. XRPL-specific-idstring Generation Method -XRPL DID MUST be unique within the XRPL network. - -`xrpl-specific-idstring` is the `AccountID` or the hex of `master public key` of the `DID` object's account. See [this](https://xrpl.org/accounts.html#address-encoding) for more details on XRPL public keys. - -Example: -A valid DID for an XRPL network may be -``` -did:xrpl:1:rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh -``` -or -``` -did:xrpl:1:0330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD020 -``` -The above DIDs are case-insensitive and will resolve to the same `DID` object. - -# 5. CRUD Operations -In this section we outline the following four CRUD operations for ``did:xrpl`` method. -- `Create` -- `Read` -- `Update` -- `Delete` - -## 5.1. DIDSet Transaction -The proposal introduces a new transaction type: **`DIDSet`** that can be used to: -- `Create` a new `DID` object, -- `Update` the existing `DID` object. - -### 5.1.1 Example **`DIDSet`** JSON -``` -{ - "TransactionType": "DIDSet", - "Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", - "Fee": "10", - "Sequence": 391, - "URI": "ipfs://bafybeigdyrzt5sfp7udm7hu76uh7y26nf4dfuylqabf3oclgtqy55fbzdi", - "Data": , - "SigningPubKey":"0330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD020", - ... - - } -``` -## Create -If the `DID` object associated with the `Account` does not exist, - - If both `URI` and `Data` fields are not present in the transaction, then transaction fails. - - Otherwise, a successful `DIDSet` transaction creates a new `DID` object with the following object ID: - - `SHA-512Half` of the following values, concatenated in order: - - - The `DID` space key (`0x0049`) - - The Account ID of the `Account`, i.e. rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh - -#### DID associated with this object is: -``` -did:xrpl:1:rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh -``` -or - -``` -did:xrpl:1:0330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD020 -``` - -### Implicit DID document -Some minimalistic use cases might only need signatures and simple authorization tokens, but don't need support for multiple keys or devices, complex organizational hierarchies and other advanced rights management features. - -To lower the entry level, we do not always require registering a `DID` by publishing a reference to or the DID Document on the ledger. If there's no explicitly registered `DID` found on the ledger then an implicit document is used instead as a default. Any update on this implicit document requires registering the `DID` object and applied changes on the ledger to be valid. - -For example, the implicit DID Document of `did:xrpl:1:0330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD020` enables only a single key 0330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD020 to authorize changes on the DID document or sign credentials in the name of the DID. - -## Update -If the `DID` object associated with the `Account` exists, - - If `URI`, `Data` and `DIDDocument` fields are not present, then transaction fails. - - Otherwise, a successful `DIDSet` transaction updates this object. - -### 5.1.2. Transaction-specific fields -| Field Name | Required? | JSON Type | Internal Type -| ---------------- |:-----------------: | :-------: | :---------------: -| `TransactionType`|:heavy_check_mark: | `string` | `UINT16` | - -Indicates the new transaction type **`DIDSet`**. The integer value is 40. - ---- -| Field Name | Required? | JSON Type | Internal Type -| ---------------- |:-----------------: | :-------: | :---------------: -| `Account` |:heavy_check_mark: | `string` | `AccountID` | - -Indicates the account which initiates the `DIDSet` transaction. This account MUST be a funded account on ledger. - ---- -| Field Name | Required? | JSON Type | Internal Type | -| --------------------- | :-----------------: | :-------: | :-------------: | -| `Fee` | :heavy_check_mark: | `number` | `Amount` | - -Indicates the fee that the account submitting this transaction is willing to pay. - ---- -| Field Name | Required? | JSON Type | Internal Type | -| -----------| :-----------------: | :-------: | :-------------: | -| `URI` | | `string` | `BLOB` | - -Indicates the `URI` field for this object. - ---- -| Field Name | Required? | JSON Type | Internal Type | -| -----------| :-----------------: | :-------: | :-------------: | -| `Data` | | `string` | `BLOB` | - -Indicates the `Data` field for this object. - ---- - -| Field Name | Required? | JSON Type | Internal Type -| -------------| :----------------: | :-------: | :-----------: -| `DIDDocument` | | `string` | `BLOB` | - -Indicates the DID document for this object. - -:notebook: If the `URI`, `Data`, or `DIDDocument` fields are missing, they will remain unchanged. However, if they contain an empty string, they will be deleted, otherwise, they will be updated. - -## 5.2. Read - -The initial step in utilizing a DID for an application may involve resolving the DID to access the underlying DID Document or attestations. This resolution process unveils the cryptographic material and service endpoints linked to the specific DID. - -In the case of XRPL DID, the `read` operation facilitates the resolution to the associated `DID` object. Upon successful resolution, applications can retrieve and utilize the relevant `URI` and/or `Data`, and/or `DIDDocument` fields contained within the `DID` object: - -Given the input DID for an account, follow these steps: - -- Retrieve the xrpl-specific-idstring of the DID. - -- If the xrpl-specific-idstring represents a public key: - - - Compute the Account ID using the method described [here](https://xrpl.org/accounts.html#address-encoding). - -- Retrieve the contents of the corresponding `DID` object in its raw format using the XRPL's [`account_objects`]( https://xrpl.org/account_objects.html#) command. Use the `account` field to specify the Account ID to retrieve all objects owned by that account, including `DID` object in the raw ledger format. Or optionally use the `type` field to filter the results by `ledger_entry` type, i.e. `DID` to retrieve the contents of just the `DID` object. - -### Example -Given the DID **did:xrpl:1:rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn**, do the following: -- Retrieve `rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn` -- Perform the `account_objects` method request to retrieve the contents of `DID` object: -``` -{ - "method": "account_objects", - "params": [ - { - "account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", - "ledger_index": "validated", - "type": "DID" - } - ] -} -``` - -A sample response to the above query might look like this: - -``` -200 OK -{ - "result": { - "account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", - "account_objects": [ - { - "URI":"ipfs://bafybeigdyrzt5sfp7udm7hu76uh7y26nf4dfuylqabf3oclgtqy55fbzdi" - } - ], - "validated": true - } -} - -``` -Upon receiving this response, an IPFS address (CAS) can be retrieved from the `URI` field. This address can then be resolved to retrieve the corresponding DID Document. - -:notebook: It is recommended that the applications implementing this method extend it to enable DID document fetching from the retrieved URI. - -Alternatively, one can use the [`ledger_entry`](https://xrpl.org/ledger_entry.html#ledger_entry) method to retrieve a single ledger entry (in this case `DID`) from the XRP Ledger in its raw format. - -## 5.3. DIDDelete Transaction -XRP ledger `DID` object owner or controller MAY want to delete the object. For this, we introduce a new transaction type called **`DIDDelete`**. A successful transaction will remove the ledger object and reduce the reserve requirement of the owner account. - -### 5.3.1. Example **`DIDDelete`** JSON -``` -{ - "TransactionType": "DIDDelete", - "Account": "rp4pqYgrTAtdPHuZd1ZQWxrzx45jxYcZex", - "Fee": "12", - "Sequence": 391, - "SigningPubKey":"0293A815C095DBA82FAC597A6BB9D338674DB93168156D84D18417AD509FFF5904", - "TxnSignature":"3044022011E9A7EE3C7AE9D202848390522E6840F7F3ED098CD13E...", - ... -} -``` -A successful `DIDDelete` transaction deletes the `DID` object corresponding to the `Account` - -### 5.3.2. Transaction-Specific Fields - -| Field Name | Required? | JSON Type | Internal Type -| ---------------- |:-----------------: | :-------: | :---------------: -| `TransactionType`|:heavy_check_mark: | `string` | `UINT16` | - -Indicates the new transaction type **`DIDDelete`**. The integer value is 41. - ---- -| Field Name | Required? | JSON Type | Internal Type | -| -----------| :-----------------: | :-------: | :-------------: | -| `Account` | :heavy_check_mark: | `string` | `AccountID` | - -Indicates the account that initiated the transaction. - ---- -| Field Name | Required? | JSON Type | Internal Type | -| -----------| :-----------------: | :-------: | :-------------: | -| `Fee` | :heavy_check_mark: | `string` | `Amount` | - -Indicates the fee that the account is willing to pay for this transaction. - - - -# 6. Privacy and Security Considerations -There are several security and privacy considerations that implementers would want to take into consideration when implementing this specification. - -## 6.1. Key Management - -The entity which controls the private key associated with the `DID` object, i.e. the XRPL `Account` also effectively controls the reference to the DID Document which the DID resolves to. Thus great care should be taken to ensure that the private key is kept private. Methods for ensuring key privacy are outside the scope of this document. - - -## 6.2. DID Document Public Profile -The DID document or other data associated with the XRPL DID's `URI` and/or `Data`, and/or `DIDDocument` fields can contain any content, though it is recommended that it conforms to the W3C DID Document and Verifiable Credentials (VC) specification. As anchored DIDs on XRPL can be resolved by anyone, care should be taken to only update to resolve DID Documents and data which DO NOT expose any sensitive personal information, or information which one may not wish to be public. DID documents should be limited to verification methods and service endpoints, and SHOULD not store any personal information. - -## 6.3. IPFS and Canonicity -IPFS allows anyone to store content publicly on the nodes in a distributed network. A common misconception is that anyone can edit content, however the content-addressability of IPFS means that this new edited content will have a different address to the original. While any entity can copy a DID Document anchored with an XRPL account's `URI`, they cannot change the document that a DID resolves to via the XRPL `account_objects` resolution unless they control the private key which created the corresponding `DID` object. - -For more, see [§ 10. Privacy Considerations](https://www.w3.org/TR/did-core/#privacy-considerations) in did-core. - -# 7. Reference Implementations -TBD - -# 8. Appendices -## Appendix 1. DID Document - -A DID is associated with a DID document. A DID document contains the necessary information to cryptographically verify the identity of the DID subject. W3C defines the [core properties](https://www.w3.org/TR/did-core/#core-properties) in a DID document, that describe relationships between the DID subject and the value of the property. For example, a DID document could contain cryptographic public keys such that the DID subject can use it to authenticate itself and proves its association with the DID. Usually, a DID document can be serialized to JSON representation or JSON-LD representation (see [DIDs v1.0]). - -Applications may choose one of the following for the DID document associated with a DID: -- Store a reference on the ledger in the `URI` field of `DID` object to the DID document stored in one or more parts on other decentralized storage networks such as IPFS or STORJ. -- Store a minimal DID document in the `Data` field of the `DID` object. -- Specify a minimal implicit DID document generated from the DID and other available public information. - -While not normative, a sample XRPL DID Document MAY look like: -``` -{ - "@context" : "https://w3id.org/did/v1", - "id" : "did:xrpl:1:rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", - "publicKey" : [ - { - "id" : "did:xrpl:1:rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn #keys-1", - "type" : ["CryptographicKey", "EcdsaKoblitzPublicKey"], - "curve" : "secp256k1", - "expires" : 15674657, - "publicKeyHex": "04f42987b7faee8b95e2c3a3345224f00e00dfc67ba882…." - } ] -} -``` - - W3C defines the [core properties](https://www.w3.org/TR/did-core/#core-properties) in a DID document, that describe relationships between the DID subject and the value of the property. - - -## Appendix 2. Universal Resolver -A Universal Resolver is an identifier resolver that works with any decentralized identifier system, including W3C DIDs. Refer [here](https://github.com/decentralized-identity/universal-resolver). A driver for XRPL DID method resolution will be added to universal resolver configurations to make it publicly accessible. - -## Appendix 3. Frequently Asked Questions -Q: Why use "Data" as the field name instead of a more specific term? - -A: The term "Data" was chosen to maintain flexibility and inclusivity within the specification. While some issuers refer to this information as "Attestations," others may use alternative terminology such as "public validations" or other terms. By using the term "Data," we aim to ensure that the specification remains adaptable to various implementations and promotes interoperability and broader applicability across the ecosystem of decentralized identity systems. \ No newline at end of file From f868f4349726301ce3e9efbf56d487ea77cbce24 Mon Sep 17 00:00:00 2001 From: Aanchal Malhotra Date: Thu, 28 Sep 2023 17:46:33 -0400 Subject: [PATCH 14/17] Add files via upload --- XLS-40.md | 416 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 416 insertions(+) create mode 100644 XLS-40.md diff --git a/XLS-40.md b/XLS-40.md new file mode 100644 index 00000000..039a5200 --- /dev/null +++ b/XLS-40.md @@ -0,0 +1,416 @@ +
    
+Title:        Decentralized Identity on XRP Ledger
+Revision:     1 (2023-09-28)
+
+
Author: Aanchal Malhotra +Affiliation: Ripple + +
+ +# 1. Abstract +Self-sovereign identity, defined as a lifetime portable digital identity that does not depend on any centralized authority, requires a new class of identifier that fulfills the following four requirements: persistence, global resolvability, cryptographic verifiability, and decentralization. [World Wide Web Consortium](https://www.w3.org/2022/07/pressrelease-did-rec.html.en) (W3C) standardized Decentralized Identifiers (DIDs) are a new type of identifier that enable verifiable, self-sovereign digital identity and are designed to be compatible with any distributed ledger or network. In the context of digital identities, W3C's standards for DIDs and Verifiable Credentials (VCs) are rapidly gaining traction, especially in blockchain-related domains. In this document we propose to implement native support for W3C DIDs on XRP Ledger. + +To this end, we specify the following on XRPL: +- A new `DID method` that describes: + - The format for XRP ledger DID, and + - Defines how XRP ledger DIDs are generated +- How to do `CRUD operations` on XRP ledger DIDs + +This specification conforms to the requirements specified in the [DID v1.0](https://www.w3.org/TR/did-core/) specification currently recommended by the W3C Credentials Community Group. + +# 2. Principles & Goals +## 2.1. Principles + +This proposal chooses to recommend W3C DID identity standard to satisfy the following first principles: + +- **Decentralized:** Requires no central issuing agency and functions effectively in Decentralized Finance. + +- **Persistent and Portable:** Inherently persistent and long-lived, not requiring the continued operation of any underlying organization and portable between different applications. + +- **Cryptographically Verifiable:** Based on cryptographic proofs rather than out-of-band trust. + +- **Universally Resolvable and Interoperable:** Open to any solution that recognizes the common W3C DID standards and requires no one specific software vendor implementation. + + +## 2.2. Goals & Non-Goals + +- This document aims to define DID identifier format for XRP ledger conformant to W3C DID standards that can be created and owned by any XRPL account holder, and specify definitions for DID methods to create, read, update and delete DID (data) that can be implemented by any service, wallet, or application. + +- This proposal is NOT intended as a competing decentralized identity standard; it aims to leverage existing (and emerging) decentralized identity standard proposed by W3C. + +- The proposal is motivated to enable **individual users** to create, and manage their decentralized identifiers while having complete control over the private keys and contents of the identity object. + +# 3. New On-Ledger Objects and Transactions +We propose one new ledger object and two new transaction types. +- **DID** is a new ledger object that is unique to an XRPL account and may contain a reference to, or the hash of, or the [W3C DID document](https://w3c-ccg.github.io/did-primer/#did-documents) itself associated with the corresponding DID. +- **DIDSet** is a new transaction type used to perform the following two operations: + - `Create` the new ledger object `DID` with `URI`, and/or `Data` fields, thus adding the required reserve towards the account that initiated the transaction. + - `Update` the mutable `URI` and `Data` fields of the `DID` object. +- **DIDDelete** is a new transaction type used to delete the `DID` object, thus reducing the reserve requirement towards the account that created the object. + +# 4. XRPL Decentralized Identifier (DID) Specification +In this section we specify the implementation details of W3C DID standard that are specific to XRP Ledger. + +## 4.1. The `DID` Object +We propose a new ledger object called **`DID`** that holds references to or data associated with a single DID. The `DID` object is created and updated using the `DIDSet` transaction and is deleted using the `DIDDelete` transaction. + +### 4.1.1. Object Fields +`DID` object may have the following required and optional fields. + +| Field Name | Required? | JSON Type | Internal Type +| ----------------- | :----------------: | :-------: | :-----------: +| `LedgerEntryType` | :heavy_check_mark: | `string` | `UINT16` | + +Identifies the type of ledger object. The proposal recommends the value `0x0049` as the reserved entry type. + +--- +| Field Name | Required? | JSON Type | Internal Type +| ----------------- | :----------------: | :-------: | :-----------: +| `PreviousTxnID` | :heavy_check_mark: | `string` | `Hash256` | + +The identifying hash of the transaction that most recently modified this object. + +--- +| Field Name | Required? | JSON Type | Internal Type +| ----------------- | :----------------: | :-------: | :-----------: +| `PreviousTxnLgrSeq` | :heavy_check_mark: | `number` | `UINT32` | + +The index of the ledger that contains the transaction that most recently modified this object. + +--- + + +| Field Name | Required? | JSON Type | Internal Type +| ----------------- | :----------------: | :-------: | :-----------: +| `URI` | | `string` | `BLOB` | + +`URI` specifies a Universal Resource Identifier, a.k.a. URI that SHOULD point to the corresponding DID document or to the data associated with the DID. This field could be an HTTP(S) URL or IPFS URI. The `URI` field is NOT checked for validity, but the field is limited to a maximum length of 256 bytes. + +--- +| Field Name | Required? | JSON Type | Internal Type +| -------------| :----------------: | :-------: | :-----------: +| `Data` | | `string` | `BLOB` | + +`Data` field SHOULD contain the public attestations of identity credentials associated with the DID. The `Data` field is NOT checked for validity, but the field is limited to a maximum length of 256 bytes. + +--- +| Field Name | Required? | JSON Type | Internal Type +| -------------| :----------------: | :-------: | :-----------: +| `DIDDocument` | | `string` | `BLOB` | + +`DIDDocument` field SHOULD contain the DID document per W3C standards associated with the DID. The field is NOT checked for validity, and is limited to a maximum length of 256 bytes. + +Note: +- Either `URI`, `Data` or `DIDDocument` field MUST be present to create and update the `DID` object. +- All `URI`, `Data` and `DIDDocument` fields MUST be absent to delete the `DID` object. + + +### 4.1.2. The `DID` Object ID Format +`DID` object may contain public data associated with the XRPL account's identity. This requires the `DID` to be: +- Unique in the XRPL namespace, and +- Uniquely associated with the XRPL account. + +We compute the `DID` object ID, a.k.a., `DIDID` as the `SHA-512Half` of the following values, concatenated in order: + +- The `DID` space key (`0x0049`) +- The Account ID + +### 4.1.3. Reserve Requirements +The account that creates the `DID` object will incur one owner reserve ~2 XRP at the time of writing this document. + +## 4.2. XRP Ledger DID Method Specification +In this section, we describe the DID method specification that conforms to the requirements specified in the DID specification currently published by the W3C Credentials Community Group. For more information about DIDs and DID method specifications, refer to the DID [Primer](https://github.com/WebOfTrustInfo/rwot5-boston/blob/master/topics-and-advance-readings/did-primer.md). + +### 4.2.1. XRP Ledger DID Scheme +The DID format as defined by W3C is as follows: +``` +"did:" method-name ":" method-specific-idstring +``` +We propose the following format for DIDs on XRPL: +``` +"did:xrpl": network-id: xrpl-specific-idstring +``` + +The components specific to the XRPL network are the following: + +- `method-name`: The `"xrpl"` namestring specifies that this is a DID for XRP Ledger. +A DID that uses this method MUST begin with the following prefix: `did:xrpl`. Per the DID specification, this string MUST be in lowercase. The remainder of the DID, after the prefix, is specified below. + +- `method-specific-idstring` is formed by `network-id` and `xrpl-specific-idstring` + + - `network-id`: `network-id` is a chain ID which is an identifier of XRP ledger networks. It specifies the underlying network instance where the `DID` is stored. Per [XLS-37d specification](https://github.com/XRPLF/rippled/pull/4418), in XRPL Protocol Chains the Network ID should match the chosen peer port. + + - `xrpl-specific-idstring` is generated as described in the next section. + + +### 4.2.2. XRPL-specific-idstring Generation Method +XRPL DID MUST be unique within the XRPL network. + +`xrpl-specific-idstring` is the `AccountID` or the hex of `master public key` of the `DID` object's account. See [this](https://xrpl.org/accounts.html#address-encoding) for more details on XRPL public keys. + +Example: +A valid DID for an XRPL network may be +``` +did:xrpl:1:rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh +``` +or +``` +did:xrpl:1:0330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD020 +``` +The above DIDs are case-insensitive and will resolve to the same `DID` object. + +# 5. CRUD Operations +In this section we outline the following four CRUD operations for ``did:xrpl`` method. +- `Create` +- `Read` +- `Update` +- `Delete` + +## 5.1. DIDSet Transaction +The proposal introduces a new transaction type: **`DIDSet`** that can be used to: +- `Create` a new `DID` object, +- `Update` the existing `DID` object. + +### 5.1.1 Example **`DIDSet`** JSON +``` +{ + "TransactionType": "DIDSet", + "Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", + "Fee": "10", + "Sequence": 391, + "URI": "ipfs://bafybeigdyrzt5sfp7udm7hu76uh7y26nf4dfuylqabf3oclgtqy55fbzdi", + "Data": , + "SigningPubKey":"0330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD020", + ... + + } +``` +## Create +If the `DID` object associated with the `Account` does not exist, + - If both `URI` and `Data` fields are not present in the transaction, then transaction fails. + - Otherwise, a successful `DIDSet` transaction creates a new `DID` object with the following object ID: + + `SHA-512Half` of the following values, concatenated in order: + + - The `DID` space key (`0x0049`) + - The Account ID of the `Account`, i.e. rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh + +#### DID associated with this object is: +``` +did:xrpl:1:rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh +``` +or + +``` +did:xrpl:1:0330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD020 +``` + +### Implicit DID document +Some minimalistic use cases might only need signatures and simple authorization tokens, but don't need support for multiple keys or devices, complex organizational hierarchies and other advanced rights management features. + +To lower the entry level, we do not always require registering a `DID` by publishing a reference to or the DID Document on the ledger. If there's no explicitly registered `DID` found on the ledger then an implicit document is used instead as a default. Any update on this implicit document requires registering the `DID` object and applied changes on the ledger to be valid. + +For example, the implicit DID Document of `did:xrpl:1:0330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD020` enables only a single key 0330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD020 to authorize changes on the DID document or sign credentials in the name of the DID. + +## Update +If the `DID` object associated with the `Account` exists, + - If `URI`, `Data` and `DIDDocument` fields are not present, then transaction fails. + - Otherwise, a successful `DIDSet` transaction updates this object. + +### 5.1.2. Transaction-specific fields +| Field Name | Required? | JSON Type | Internal Type +| ---------------- |:-----------------: | :-------: | :---------------: +| `TransactionType`|:heavy_check_mark: | `string` | `UINT16` | + +Indicates the new transaction type **`DIDSet`**. The integer value is 40. + +--- +| Field Name | Required? | JSON Type | Internal Type +| ---------------- |:-----------------: | :-------: | :---------------: +| `Account` |:heavy_check_mark: | `string` | `AccountID` | + +Indicates the account which initiates the `DIDSet` transaction. This account MUST be a funded account on ledger. + +--- +| Field Name | Required? | JSON Type | Internal Type | +| --------------------- | :-----------------: | :-------: | :-------------: | +| `Fee` | :heavy_check_mark: | `number` | `Amount` | + +Indicates the fee that the account submitting this transaction is willing to pay. + +--- +| Field Name | Required? | JSON Type | Internal Type | +| -----------| :-----------------: | :-------: | :-------------: | +| `URI` | | `string` | `BLOB` | + +Indicates the `URI` field for this object. + +--- +| Field Name | Required? | JSON Type | Internal Type | +| -----------| :-----------------: | :-------: | :-------------: | +| `Data` | | `string` | `BLOB` | + +Indicates the `Data` field for this object. + +--- + +| Field Name | Required? | JSON Type | Internal Type +| -------------| :----------------: | :-------: | :-----------: +| `DIDDocument` | | `string` | `BLOB` | + +Indicates the DID document for this object. + +:notebook: If the `URI`, `Data`, or `DIDDocument` fields are missing, they will remain unchanged. However, if they contain an empty string, they will be deleted, otherwise, they will be updated. + +## 5.2. Read + +The initial step in utilizing a DID for an application may involve resolving the DID to access the underlying DID Document or attestations. This resolution process unveils the cryptographic material and service endpoints linked to the specific DID. + +In the case of XRPL DID, the `read` operation facilitates the resolution to the associated `DID` object. Upon successful resolution, applications can retrieve and utilize the relevant `URI` and/or `Data`, and/or `DIDDocument` fields contained within the `DID` object: + +Given the input DID for an account, follow these steps: + +- Retrieve the xrpl-specific-idstring of the DID. + +- If the xrpl-specific-idstring represents a public key: + + - Compute the Account ID using the method described [here](https://xrpl.org/accounts.html#address-encoding). + +- Retrieve the contents of the corresponding `DID` object in its raw format using the XRPL's [`account_objects`]( https://xrpl.org/account_objects.html#) command. Use the `account` field to specify the Account ID to retrieve all objects owned by that account, including `DID` object in the raw ledger format. Or optionally use the `type` field to filter the results by `ledger_entry` type, i.e. `DID` to retrieve the contents of just the `DID` object. + +### Example +Given the DID **did:xrpl:1:rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn**, do the following: +- Retrieve `rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn` +- Perform the `account_objects` method request to retrieve the contents of `DID` object: +``` +{ + "method": "account_objects", + "params": [ + { + "account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", + "ledger_index": "validated", + "type": "DID" + } + ] +} +``` + +A sample response to the above query might look like this: + +``` +200 OK +{ + "result": { + "account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", + "account_objects": [ + { + "URI":"ipfs://bafybeigdyrzt5sfp7udm7hu76uh7y26nf4dfuylqabf3oclgtqy55fbzdi" + } + ], + "validated": true + } +} + +``` +Upon receiving this response, an IPFS address (CAS) can be retrieved from the `URI` field. This address can then be resolved to retrieve the corresponding DID Document. + +:notebook: It is recommended that the applications implementing this method extend it to enable DID document fetching from the retrieved URI. + +Alternatively, one can use the [`ledger_entry`](https://xrpl.org/ledger_entry.html#ledger_entry) method to retrieve a single ledger entry (in this case `DID`) from the XRP Ledger in its raw format. + +## 5.3. DIDDelete Transaction +XRP ledger `DID` object owner or controller MAY want to delete the object. For this, we introduce a new transaction type called **`DIDDelete`**. A successful transaction will remove the ledger object and reduce the reserve requirement of the owner account. + +### 5.3.1. Example **`DIDDelete`** JSON +``` +{ + "TransactionType": "DIDDelete", + "Account": "rp4pqYgrTAtdPHuZd1ZQWxrzx45jxYcZex", + "Fee": "12", + "Sequence": 391, + "SigningPubKey":"0293A815C095DBA82FAC597A6BB9D338674DB93168156D84D18417AD509FFF5904", + "TxnSignature":"3044022011E9A7EE3C7AE9D202848390522E6840F7F3ED098CD13E...", + ... +} +``` +A successful `DIDDelete` transaction deletes the `DID` object corresponding to the `Account` + +### 5.3.2. Transaction-Specific Fields + +| Field Name | Required? | JSON Type | Internal Type +| ---------------- |:-----------------: | :-------: | :---------------: +| `TransactionType`|:heavy_check_mark: | `string` | `UINT16` | + +Indicates the new transaction type **`DIDDelete`**. The integer value is 41. + +--- +| Field Name | Required? | JSON Type | Internal Type | +| -----------| :-----------------: | :-------: | :-------------: | +| `Account` | :heavy_check_mark: | `string` | `AccountID` | + +Indicates the account that initiated the transaction. + +--- +| Field Name | Required? | JSON Type | Internal Type | +| -----------| :-----------------: | :-------: | :-------------: | +| `Fee` | :heavy_check_mark: | `string` | `Amount` | + +Indicates the fee that the account is willing to pay for this transaction. + + + +# 6. Privacy and Security Considerations +There are several security and privacy considerations that implementers would want to take into consideration when implementing this specification. + +## 6.1. Key Management + +The entity which controls the private key associated with the `DID` object, i.e. the XRPL `Account` also effectively controls the reference to the DID Document which the DID resolves to. Thus great care should be taken to ensure that the private key is kept private. Methods for ensuring key privacy are outside the scope of this document. + + +## 6.2. DID Document Public Profile +The DID document or other data associated with the XRPL DID's `URI` and/or `Data`, and/or `DIDDocument` fields can contain any content, though it is recommended that it conforms to the W3C DID Document and Verifiable Credentials (VC) specification. As anchored DIDs on XRPL can be resolved by anyone, care should be taken to only update to resolve DID Documents and data which DO NOT expose any sensitive personal information, or information which one may not wish to be public. DID documents should be limited to verification methods and service endpoints, and SHOULD not store any personal information. + +## 6.3. IPFS and Canonicity +IPFS allows anyone to store content publicly on the nodes in a distributed network. A common misconception is that anyone can edit content, however the content-addressability of IPFS means that this new edited content will have a different address to the original. While any entity can copy a DID Document anchored with an XRPL account's `URI`, they cannot change the document that a DID resolves to via the XRPL `account_objects` resolution unless they control the private key which created the corresponding `DID` object. + +For more, see [§ 10. Privacy Considerations](https://www.w3.org/TR/did-core/#privacy-considerations) in did-core. + +# 7. Reference Implementations +TBD + +# 8. Appendices +## Appendix 1. DID Document + +A DID is associated with a DID document. A DID document contains the necessary information to cryptographically verify the identity of the DID subject. W3C defines the [core properties](https://www.w3.org/TR/did-core/#core-properties) in a DID document, that describe relationships between the DID subject and the value of the property. For example, a DID document could contain cryptographic public keys such that the DID subject can use it to authenticate itself and proves its association with the DID. Usually, a DID document can be serialized to JSON representation or JSON-LD representation (see [DIDs v1.0]). + +Applications may choose one of the following for the DID document associated with a DID: +- Store a reference on the ledger in the `URI` field of `DID` object to the DID document stored in one or more parts on other decentralized storage networks such as IPFS or STORJ. +- Store a minimal DID document in the `Data` field of the `DID` object. +- Specify a minimal implicit DID document generated from the DID and other available public information. + +While not normative, a sample XRPL DID Document MAY look like: +``` +{ + "@context" : "https://w3id.org/did/v1", + "id" : "did:xrpl:1:rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", + "publicKey" : [ + { + "id" : "did:xrpl:1:rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn #keys-1", + "type" : ["CryptographicKey", "EcdsaKoblitzPublicKey"], + "curve" : "secp256k1", + "expires" : 15674657, + "publicKeyHex": "04f42987b7faee8b95e2c3a3345224f00e00dfc67ba882…." + } ] +} +``` + + W3C defines the [core properties](https://www.w3.org/TR/did-core/#core-properties) in a DID document, that describe relationships between the DID subject and the value of the property. + + +## Appendix 2. Universal Resolver +A Universal Resolver is an identifier resolver that works with any decentralized identifier system, including W3C DIDs. Refer [here](https://github.com/decentralized-identity/universal-resolver). A driver for XRPL DID method resolution will be added to universal resolver configurations to make it publicly accessible. + +## Appendix 3. Frequently Asked Questions +Q: Why use "Data" as the field name instead of a more specific term? + +A: The term "Data" was chosen to maintain flexibility and inclusivity within the specification. While some issuers refer to this information as "Attestations," others may use alternative terminology such as "public validations" or other terms. By using the term "Data," we aim to ensure that the specification remains adaptable to various implementations and promotes interoperability and broader applicability across the ecosystem of decentralized identity systems. \ No newline at end of file From 43d7a6b510fc23c49ba1e1cb8b73cdad3595fbef Mon Sep 17 00:00:00 2001 From: Aanchal Malhotra Date: Thu, 28 Sep 2023 17:46:59 -0400 Subject: [PATCH 15/17] Delete XLS-40.md --- XLS-40.md | 416 ------------------------------------------------------ 1 file changed, 416 deletions(-) delete mode 100644 XLS-40.md diff --git a/XLS-40.md b/XLS-40.md deleted file mode 100644 index 039a5200..00000000 --- a/XLS-40.md +++ /dev/null @@ -1,416 +0,0 @@ -
    
-Title:        Decentralized Identity on XRP Ledger
-Revision:     1 (2023-09-28)
-
-
Author: Aanchal Malhotra -Affiliation: Ripple - -
- -# 1. Abstract -Self-sovereign identity, defined as a lifetime portable digital identity that does not depend on any centralized authority, requires a new class of identifier that fulfills the following four requirements: persistence, global resolvability, cryptographic verifiability, and decentralization. [World Wide Web Consortium](https://www.w3.org/2022/07/pressrelease-did-rec.html.en) (W3C) standardized Decentralized Identifiers (DIDs) are a new type of identifier that enable verifiable, self-sovereign digital identity and are designed to be compatible with any distributed ledger or network. In the context of digital identities, W3C's standards for DIDs and Verifiable Credentials (VCs) are rapidly gaining traction, especially in blockchain-related domains. In this document we propose to implement native support for W3C DIDs on XRP Ledger. - -To this end, we specify the following on XRPL: -- A new `DID method` that describes: - - The format for XRP ledger DID, and - - Defines how XRP ledger DIDs are generated -- How to do `CRUD operations` on XRP ledger DIDs - -This specification conforms to the requirements specified in the [DID v1.0](https://www.w3.org/TR/did-core/) specification currently recommended by the W3C Credentials Community Group. - -# 2. Principles & Goals -## 2.1. Principles - -This proposal chooses to recommend W3C DID identity standard to satisfy the following first principles: - -- **Decentralized:** Requires no central issuing agency and functions effectively in Decentralized Finance. - -- **Persistent and Portable:** Inherently persistent and long-lived, not requiring the continued operation of any underlying organization and portable between different applications. - -- **Cryptographically Verifiable:** Based on cryptographic proofs rather than out-of-band trust. - -- **Universally Resolvable and Interoperable:** Open to any solution that recognizes the common W3C DID standards and requires no one specific software vendor implementation. - - -## 2.2. Goals & Non-Goals - -- This document aims to define DID identifier format for XRP ledger conformant to W3C DID standards that can be created and owned by any XRPL account holder, and specify definitions for DID methods to create, read, update and delete DID (data) that can be implemented by any service, wallet, or application. - -- This proposal is NOT intended as a competing decentralized identity standard; it aims to leverage existing (and emerging) decentralized identity standard proposed by W3C. - -- The proposal is motivated to enable **individual users** to create, and manage their decentralized identifiers while having complete control over the private keys and contents of the identity object. - -# 3. New On-Ledger Objects and Transactions -We propose one new ledger object and two new transaction types. -- **DID** is a new ledger object that is unique to an XRPL account and may contain a reference to, or the hash of, or the [W3C DID document](https://w3c-ccg.github.io/did-primer/#did-documents) itself associated with the corresponding DID. -- **DIDSet** is a new transaction type used to perform the following two operations: - - `Create` the new ledger object `DID` with `URI`, and/or `Data` fields, thus adding the required reserve towards the account that initiated the transaction. - - `Update` the mutable `URI` and `Data` fields of the `DID` object. -- **DIDDelete** is a new transaction type used to delete the `DID` object, thus reducing the reserve requirement towards the account that created the object. - -# 4. XRPL Decentralized Identifier (DID) Specification -In this section we specify the implementation details of W3C DID standard that are specific to XRP Ledger. - -## 4.1. The `DID` Object -We propose a new ledger object called **`DID`** that holds references to or data associated with a single DID. The `DID` object is created and updated using the `DIDSet` transaction and is deleted using the `DIDDelete` transaction. - -### 4.1.1. Object Fields -`DID` object may have the following required and optional fields. - -| Field Name | Required? | JSON Type | Internal Type -| ----------------- | :----------------: | :-------: | :-----------: -| `LedgerEntryType` | :heavy_check_mark: | `string` | `UINT16` | - -Identifies the type of ledger object. The proposal recommends the value `0x0049` as the reserved entry type. - ---- -| Field Name | Required? | JSON Type | Internal Type -| ----------------- | :----------------: | :-------: | :-----------: -| `PreviousTxnID` | :heavy_check_mark: | `string` | `Hash256` | - -The identifying hash of the transaction that most recently modified this object. - ---- -| Field Name | Required? | JSON Type | Internal Type -| ----------------- | :----------------: | :-------: | :-----------: -| `PreviousTxnLgrSeq` | :heavy_check_mark: | `number` | `UINT32` | - -The index of the ledger that contains the transaction that most recently modified this object. - ---- - - -| Field Name | Required? | JSON Type | Internal Type -| ----------------- | :----------------: | :-------: | :-----------: -| `URI` | | `string` | `BLOB` | - -`URI` specifies a Universal Resource Identifier, a.k.a. URI that SHOULD point to the corresponding DID document or to the data associated with the DID. This field could be an HTTP(S) URL or IPFS URI. The `URI` field is NOT checked for validity, but the field is limited to a maximum length of 256 bytes. - ---- -| Field Name | Required? | JSON Type | Internal Type -| -------------| :----------------: | :-------: | :-----------: -| `Data` | | `string` | `BLOB` | - -`Data` field SHOULD contain the public attestations of identity credentials associated with the DID. The `Data` field is NOT checked for validity, but the field is limited to a maximum length of 256 bytes. - ---- -| Field Name | Required? | JSON Type | Internal Type -| -------------| :----------------: | :-------: | :-----------: -| `DIDDocument` | | `string` | `BLOB` | - -`DIDDocument` field SHOULD contain the DID document per W3C standards associated with the DID. The field is NOT checked for validity, and is limited to a maximum length of 256 bytes. - -Note: -- Either `URI`, `Data` or `DIDDocument` field MUST be present to create and update the `DID` object. -- All `URI`, `Data` and `DIDDocument` fields MUST be absent to delete the `DID` object. - - -### 4.1.2. The `DID` Object ID Format -`DID` object may contain public data associated with the XRPL account's identity. This requires the `DID` to be: -- Unique in the XRPL namespace, and -- Uniquely associated with the XRPL account. - -We compute the `DID` object ID, a.k.a., `DIDID` as the `SHA-512Half` of the following values, concatenated in order: - -- The `DID` space key (`0x0049`) -- The Account ID - -### 4.1.3. Reserve Requirements -The account that creates the `DID` object will incur one owner reserve ~2 XRP at the time of writing this document. - -## 4.2. XRP Ledger DID Method Specification -In this section, we describe the DID method specification that conforms to the requirements specified in the DID specification currently published by the W3C Credentials Community Group. For more information about DIDs and DID method specifications, refer to the DID [Primer](https://github.com/WebOfTrustInfo/rwot5-boston/blob/master/topics-and-advance-readings/did-primer.md). - -### 4.2.1. XRP Ledger DID Scheme -The DID format as defined by W3C is as follows: -``` -"did:" method-name ":" method-specific-idstring -``` -We propose the following format for DIDs on XRPL: -``` -"did:xrpl": network-id: xrpl-specific-idstring -``` - -The components specific to the XRPL network are the following: - -- `method-name`: The `"xrpl"` namestring specifies that this is a DID for XRP Ledger. -A DID that uses this method MUST begin with the following prefix: `did:xrpl`. Per the DID specification, this string MUST be in lowercase. The remainder of the DID, after the prefix, is specified below. - -- `method-specific-idstring` is formed by `network-id` and `xrpl-specific-idstring` - - - `network-id`: `network-id` is a chain ID which is an identifier of XRP ledger networks. It specifies the underlying network instance where the `DID` is stored. Per [XLS-37d specification](https://github.com/XRPLF/rippled/pull/4418), in XRPL Protocol Chains the Network ID should match the chosen peer port. - - - `xrpl-specific-idstring` is generated as described in the next section. - - -### 4.2.2. XRPL-specific-idstring Generation Method -XRPL DID MUST be unique within the XRPL network. - -`xrpl-specific-idstring` is the `AccountID` or the hex of `master public key` of the `DID` object's account. See [this](https://xrpl.org/accounts.html#address-encoding) for more details on XRPL public keys. - -Example: -A valid DID for an XRPL network may be -``` -did:xrpl:1:rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh -``` -or -``` -did:xrpl:1:0330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD020 -``` -The above DIDs are case-insensitive and will resolve to the same `DID` object. - -# 5. CRUD Operations -In this section we outline the following four CRUD operations for ``did:xrpl`` method. -- `Create` -- `Read` -- `Update` -- `Delete` - -## 5.1. DIDSet Transaction -The proposal introduces a new transaction type: **`DIDSet`** that can be used to: -- `Create` a new `DID` object, -- `Update` the existing `DID` object. - -### 5.1.1 Example **`DIDSet`** JSON -``` -{ - "TransactionType": "DIDSet", - "Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", - "Fee": "10", - "Sequence": 391, - "URI": "ipfs://bafybeigdyrzt5sfp7udm7hu76uh7y26nf4dfuylqabf3oclgtqy55fbzdi", - "Data": , - "SigningPubKey":"0330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD020", - ... - - } -``` -## Create -If the `DID` object associated with the `Account` does not exist, - - If both `URI` and `Data` fields are not present in the transaction, then transaction fails. - - Otherwise, a successful `DIDSet` transaction creates a new `DID` object with the following object ID: - - `SHA-512Half` of the following values, concatenated in order: - - - The `DID` space key (`0x0049`) - - The Account ID of the `Account`, i.e. rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh - -#### DID associated with this object is: -``` -did:xrpl:1:rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh -``` -or - -``` -did:xrpl:1:0330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD020 -``` - -### Implicit DID document -Some minimalistic use cases might only need signatures and simple authorization tokens, but don't need support for multiple keys or devices, complex organizational hierarchies and other advanced rights management features. - -To lower the entry level, we do not always require registering a `DID` by publishing a reference to or the DID Document on the ledger. If there's no explicitly registered `DID` found on the ledger then an implicit document is used instead as a default. Any update on this implicit document requires registering the `DID` object and applied changes on the ledger to be valid. - -For example, the implicit DID Document of `did:xrpl:1:0330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD020` enables only a single key 0330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD020 to authorize changes on the DID document or sign credentials in the name of the DID. - -## Update -If the `DID` object associated with the `Account` exists, - - If `URI`, `Data` and `DIDDocument` fields are not present, then transaction fails. - - Otherwise, a successful `DIDSet` transaction updates this object. - -### 5.1.2. Transaction-specific fields -| Field Name | Required? | JSON Type | Internal Type -| ---------------- |:-----------------: | :-------: | :---------------: -| `TransactionType`|:heavy_check_mark: | `string` | `UINT16` | - -Indicates the new transaction type **`DIDSet`**. The integer value is 40. - ---- -| Field Name | Required? | JSON Type | Internal Type -| ---------------- |:-----------------: | :-------: | :---------------: -| `Account` |:heavy_check_mark: | `string` | `AccountID` | - -Indicates the account which initiates the `DIDSet` transaction. This account MUST be a funded account on ledger. - ---- -| Field Name | Required? | JSON Type | Internal Type | -| --------------------- | :-----------------: | :-------: | :-------------: | -| `Fee` | :heavy_check_mark: | `number` | `Amount` | - -Indicates the fee that the account submitting this transaction is willing to pay. - ---- -| Field Name | Required? | JSON Type | Internal Type | -| -----------| :-----------------: | :-------: | :-------------: | -| `URI` | | `string` | `BLOB` | - -Indicates the `URI` field for this object. - ---- -| Field Name | Required? | JSON Type | Internal Type | -| -----------| :-----------------: | :-------: | :-------------: | -| `Data` | | `string` | `BLOB` | - -Indicates the `Data` field for this object. - ---- - -| Field Name | Required? | JSON Type | Internal Type -| -------------| :----------------: | :-------: | :-----------: -| `DIDDocument` | | `string` | `BLOB` | - -Indicates the DID document for this object. - -:notebook: If the `URI`, `Data`, or `DIDDocument` fields are missing, they will remain unchanged. However, if they contain an empty string, they will be deleted, otherwise, they will be updated. - -## 5.2. Read - -The initial step in utilizing a DID for an application may involve resolving the DID to access the underlying DID Document or attestations. This resolution process unveils the cryptographic material and service endpoints linked to the specific DID. - -In the case of XRPL DID, the `read` operation facilitates the resolution to the associated `DID` object. Upon successful resolution, applications can retrieve and utilize the relevant `URI` and/or `Data`, and/or `DIDDocument` fields contained within the `DID` object: - -Given the input DID for an account, follow these steps: - -- Retrieve the xrpl-specific-idstring of the DID. - -- If the xrpl-specific-idstring represents a public key: - - - Compute the Account ID using the method described [here](https://xrpl.org/accounts.html#address-encoding). - -- Retrieve the contents of the corresponding `DID` object in its raw format using the XRPL's [`account_objects`]( https://xrpl.org/account_objects.html#) command. Use the `account` field to specify the Account ID to retrieve all objects owned by that account, including `DID` object in the raw ledger format. Or optionally use the `type` field to filter the results by `ledger_entry` type, i.e. `DID` to retrieve the contents of just the `DID` object. - -### Example -Given the DID **did:xrpl:1:rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn**, do the following: -- Retrieve `rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn` -- Perform the `account_objects` method request to retrieve the contents of `DID` object: -``` -{ - "method": "account_objects", - "params": [ - { - "account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", - "ledger_index": "validated", - "type": "DID" - } - ] -} -``` - -A sample response to the above query might look like this: - -``` -200 OK -{ - "result": { - "account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", - "account_objects": [ - { - "URI":"ipfs://bafybeigdyrzt5sfp7udm7hu76uh7y26nf4dfuylqabf3oclgtqy55fbzdi" - } - ], - "validated": true - } -} - -``` -Upon receiving this response, an IPFS address (CAS) can be retrieved from the `URI` field. This address can then be resolved to retrieve the corresponding DID Document. - -:notebook: It is recommended that the applications implementing this method extend it to enable DID document fetching from the retrieved URI. - -Alternatively, one can use the [`ledger_entry`](https://xrpl.org/ledger_entry.html#ledger_entry) method to retrieve a single ledger entry (in this case `DID`) from the XRP Ledger in its raw format. - -## 5.3. DIDDelete Transaction -XRP ledger `DID` object owner or controller MAY want to delete the object. For this, we introduce a new transaction type called **`DIDDelete`**. A successful transaction will remove the ledger object and reduce the reserve requirement of the owner account. - -### 5.3.1. Example **`DIDDelete`** JSON -``` -{ - "TransactionType": "DIDDelete", - "Account": "rp4pqYgrTAtdPHuZd1ZQWxrzx45jxYcZex", - "Fee": "12", - "Sequence": 391, - "SigningPubKey":"0293A815C095DBA82FAC597A6BB9D338674DB93168156D84D18417AD509FFF5904", - "TxnSignature":"3044022011E9A7EE3C7AE9D202848390522E6840F7F3ED098CD13E...", - ... -} -``` -A successful `DIDDelete` transaction deletes the `DID` object corresponding to the `Account` - -### 5.3.2. Transaction-Specific Fields - -| Field Name | Required? | JSON Type | Internal Type -| ---------------- |:-----------------: | :-------: | :---------------: -| `TransactionType`|:heavy_check_mark: | `string` | `UINT16` | - -Indicates the new transaction type **`DIDDelete`**. The integer value is 41. - ---- -| Field Name | Required? | JSON Type | Internal Type | -| -----------| :-----------------: | :-------: | :-------------: | -| `Account` | :heavy_check_mark: | `string` | `AccountID` | - -Indicates the account that initiated the transaction. - ---- -| Field Name | Required? | JSON Type | Internal Type | -| -----------| :-----------------: | :-------: | :-------------: | -| `Fee` | :heavy_check_mark: | `string` | `Amount` | - -Indicates the fee that the account is willing to pay for this transaction. - - - -# 6. Privacy and Security Considerations -There are several security and privacy considerations that implementers would want to take into consideration when implementing this specification. - -## 6.1. Key Management - -The entity which controls the private key associated with the `DID` object, i.e. the XRPL `Account` also effectively controls the reference to the DID Document which the DID resolves to. Thus great care should be taken to ensure that the private key is kept private. Methods for ensuring key privacy are outside the scope of this document. - - -## 6.2. DID Document Public Profile -The DID document or other data associated with the XRPL DID's `URI` and/or `Data`, and/or `DIDDocument` fields can contain any content, though it is recommended that it conforms to the W3C DID Document and Verifiable Credentials (VC) specification. As anchored DIDs on XRPL can be resolved by anyone, care should be taken to only update to resolve DID Documents and data which DO NOT expose any sensitive personal information, or information which one may not wish to be public. DID documents should be limited to verification methods and service endpoints, and SHOULD not store any personal information. - -## 6.3. IPFS and Canonicity -IPFS allows anyone to store content publicly on the nodes in a distributed network. A common misconception is that anyone can edit content, however the content-addressability of IPFS means that this new edited content will have a different address to the original. While any entity can copy a DID Document anchored with an XRPL account's `URI`, they cannot change the document that a DID resolves to via the XRPL `account_objects` resolution unless they control the private key which created the corresponding `DID` object. - -For more, see [§ 10. Privacy Considerations](https://www.w3.org/TR/did-core/#privacy-considerations) in did-core. - -# 7. Reference Implementations -TBD - -# 8. Appendices -## Appendix 1. DID Document - -A DID is associated with a DID document. A DID document contains the necessary information to cryptographically verify the identity of the DID subject. W3C defines the [core properties](https://www.w3.org/TR/did-core/#core-properties) in a DID document, that describe relationships between the DID subject and the value of the property. For example, a DID document could contain cryptographic public keys such that the DID subject can use it to authenticate itself and proves its association with the DID. Usually, a DID document can be serialized to JSON representation or JSON-LD representation (see [DIDs v1.0]). - -Applications may choose one of the following for the DID document associated with a DID: -- Store a reference on the ledger in the `URI` field of `DID` object to the DID document stored in one or more parts on other decentralized storage networks such as IPFS or STORJ. -- Store a minimal DID document in the `Data` field of the `DID` object. -- Specify a minimal implicit DID document generated from the DID and other available public information. - -While not normative, a sample XRPL DID Document MAY look like: -``` -{ - "@context" : "https://w3id.org/did/v1", - "id" : "did:xrpl:1:rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", - "publicKey" : [ - { - "id" : "did:xrpl:1:rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn #keys-1", - "type" : ["CryptographicKey", "EcdsaKoblitzPublicKey"], - "curve" : "secp256k1", - "expires" : 15674657, - "publicKeyHex": "04f42987b7faee8b95e2c3a3345224f00e00dfc67ba882…." - } ] -} -``` - - W3C defines the [core properties](https://www.w3.org/TR/did-core/#core-properties) in a DID document, that describe relationships between the DID subject and the value of the property. - - -## Appendix 2. Universal Resolver -A Universal Resolver is an identifier resolver that works with any decentralized identifier system, including W3C DIDs. Refer [here](https://github.com/decentralized-identity/universal-resolver). A driver for XRPL DID method resolution will be added to universal resolver configurations to make it publicly accessible. - -## Appendix 3. Frequently Asked Questions -Q: Why use "Data" as the field name instead of a more specific term? - -A: The term "Data" was chosen to maintain flexibility and inclusivity within the specification. While some issuers refer to this information as "Attestations," others may use alternative terminology such as "public validations" or other terms. By using the term "Data," we aim to ensure that the specification remains adaptable to various implementations and promotes interoperability and broader applicability across the ecosystem of decentralized identity systems. \ No newline at end of file From 00daff6563c8ccad354f6a78ebab89d0524e6927 Mon Sep 17 00:00:00 2001 From: Aanchal Malhotra Date: Thu, 28 Sep 2023 18:07:57 -0400 Subject: [PATCH 16/17] Create README.md --- XLS-40/README.md | 416 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 416 insertions(+) create mode 100644 XLS-40/README.md diff --git a/XLS-40/README.md b/XLS-40/README.md new file mode 100644 index 00000000..58dbea13 --- /dev/null +++ b/XLS-40/README.md @@ -0,0 +1,416 @@ +
    
+Title:        Decentralized Identity on XRP Ledger
+Revision:     4 (2023-09-28)
+
+
Author: Aanchal Malhotra +Affiliation: Ripple + +
+ +# 1. Abstract +Self-sovereign identity, defined as a lifetime portable digital identity that does not depend on any centralized authority, requires a new class of identifier that fulfills the following four requirements: persistence, global resolvability, cryptographic verifiability, and decentralization. [World Wide Web Consortium](https://www.w3.org/2022/07/pressrelease-did-rec.html.en) (W3C) standardized Decentralized Identifiers (DIDs) are a new type of identifier that enable verifiable, self-sovereign digital identity and are designed to be compatible with any distributed ledger or network. In the context of digital identities, W3C's standards for DIDs and Verifiable Credentials (VCs) are rapidly gaining traction, especially in blockchain-related domains. In this document we propose to implement native support for W3C DIDs on XRP Ledger. + +To this end, we specify the following on XRPL: +- A new `DID method` that describes: + - The format for XRP ledger DID, and + - Defines how XRP ledger DIDs are generated +- How to do `CRUD operations` on XRP ledger DIDs + +This specification conforms to the requirements specified in the [DID v1.0](https://www.w3.org/TR/did-core/) specification currently recommended by the W3C Credentials Community Group. + +# 2. Principles & Goals +## 2.1. Principles + +This proposal chooses to recommend W3C DID identity standard to satisfy the following first principles: + +- **Decentralized:** Requires no central issuing agency and functions effectively in Decentralized Finance. + +- **Persistent and Portable:** Inherently persistent and long-lived, not requiring the continued operation of any underlying organization and portable between different applications. + +- **Cryptographically Verifiable:** Based on cryptographic proofs rather than out-of-band trust. + +- **Universally Resolvable and Interoperable:** Open to any solution that recognizes the common W3C DID standards and requires no one specific software vendor implementation. + + +## 2.2. Goals & Non-Goals + +- This document aims to define DID identifier format for XRP ledger conformant to W3C DID standards that can be created and owned by any XRPL account holder, and specify definitions for DID methods to create, read, update and delete DID (data) that can be implemented by any service, wallet, or application. + +- This proposal is NOT intended as a competing decentralized identity standard; it aims to leverage existing (and emerging) decentralized identity standard proposed by W3C. + +- The proposal is motivated to enable **individual users** to create, and manage their decentralized identifiers while having complete control over the private keys and contents of the identity object. + +# 3. New On-Ledger Objects and Transactions +We propose one new ledger object and two new transaction types. +- **DID** is a new ledger object that is unique to an XRPL account and may contain a reference to, or the hash of, or the [W3C DID document](https://w3c-ccg.github.io/did-primer/#did-documents) itself associated with the corresponding DID. +- **DIDSet** is a new transaction type used to perform the following two operations: + - `Create` the new ledger object `DID` with `URI`, and/or `Data` fields, thus adding the required reserve towards the account that initiated the transaction. + - `Update` the mutable `URI` and `Data` fields of the `DID` object. +- **DIDDelete** is a new transaction type used to delete the `DID` object, thus reducing the reserve requirement towards the account that created the object. + +# 4. XRPL Decentralized Identifier (DID) Specification +In this section we specify the implementation details of W3C DID standard that are specific to XRP Ledger. + +## 4.1. The `DID` Object +We propose a new ledger object called **`DID`** that holds references to or data associated with a single DID. The `DID` object is created and updated using the `DIDSet` transaction and is deleted using the `DIDDelete` transaction. + +### 4.1.1. Object Fields +`DID` object may have the following required and optional fields. + +| Field Name | Required? | JSON Type | Internal Type +| ----------------- | :----------------: | :-------: | :-----------: +| `LedgerEntryType` | :heavy_check_mark: | `string` | `UINT16` | + +Identifies the type of ledger object. The proposal recommends the value `0x0049` as the reserved entry type. + +--- +| Field Name | Required? | JSON Type | Internal Type +| ----------------- | :----------------: | :-------: | :-----------: +| `PreviousTxnID` | :heavy_check_mark: | `string` | `Hash256` | + +The identifying hash of the transaction that most recently modified this object. + +--- +| Field Name | Required? | JSON Type | Internal Type +| ----------------- | :----------------: | :-------: | :-----------: +| `PreviousTxnLgrSeq` | :heavy_check_mark: | `number` | `UINT32` | + +The index of the ledger that contains the transaction that most recently modified this object. + +--- + + +| Field Name | Required? | JSON Type | Internal Type +| ----------------- | :----------------: | :-------: | :-----------: +| `URI` | | `string` | `BLOB` | + +`URI` specifies a Universal Resource Identifier, a.k.a. URI that SHOULD point to the corresponding DID document or to the data associated with the DID. This field could be an HTTP(S) URL or IPFS URI. The `URI` field is NOT checked for validity, but the field is limited to a maximum length of 256 bytes. + +--- +| Field Name | Required? | JSON Type | Internal Type +| -------------| :----------------: | :-------: | :-----------: +| `Data` | | `string` | `BLOB` | + +`Data` field SHOULD contain the public attestations of identity credentials associated with the DID. The `Data` field is NOT checked for validity, but the field is limited to a maximum length of 256 bytes. + +--- +| Field Name | Required? | JSON Type | Internal Type +| -------------| :----------------: | :-------: | :-----------: +| `DIDDocument` | | `string` | `BLOB` | + +`DIDDocument` field SHOULD contain the DID document per W3C standards associated with the DID. The field is NOT checked for validity, and is limited to a maximum length of 256 bytes. + +Note: +- Either `URI`, `Data` or `DIDDocument` field MUST be present to create and update the `DID` object. +- All `URI`, `Data` and `DIDDocument` fields MUST be absent to delete the `DID` object. + + +### 4.1.2. The `DID` Object ID Format +`DID` object may contain public data associated with the XRPL account's identity. This requires the `DID` to be: +- Unique in the XRPL namespace, and +- Uniquely associated with the XRPL account. + +We compute the `DID` object ID, a.k.a., `DIDID` as the `SHA-512Half` of the following values, concatenated in order: + +- The `DID` space key (`0x0049`) +- The Account ID + +### 4.1.3. Reserve Requirements +The account that creates the `DID` object will incur one owner reserve ~2 XRP at the time of writing this document. + +## 4.2. XRP Ledger DID Method Specification +In this section, we describe the DID method specification that conforms to the requirements specified in the DID specification currently published by the W3C Credentials Community Group. For more information about DIDs and DID method specifications, refer to the DID [Primer](https://github.com/WebOfTrustInfo/rwot5-boston/blob/master/topics-and-advance-readings/did-primer.md). + +### 4.2.1. XRP Ledger DID Scheme +The DID format as defined by W3C is as follows: +``` +"did:" method-name ":" method-specific-idstring +``` +We propose the following format for DIDs on XRPL: +``` +"did:xrpl": network-id: xrpl-specific-idstring +``` + +The components specific to the XRPL network are the following: + +- `method-name`: The `"xrpl"` namestring specifies that this is a DID for XRP Ledger. +A DID that uses this method MUST begin with the following prefix: `did:xrpl`. Per the DID specification, this string MUST be in lowercase. The remainder of the DID, after the prefix, is specified below. + +- `method-specific-idstring` is formed by `network-id` and `xrpl-specific-idstring` + + - `network-id`: `network-id` is a chain ID which is an identifier of XRP ledger networks. It specifies the underlying network instance where the `DID` is stored. Per [XLS-37d specification](https://github.com/XRPLF/rippled/pull/4418), in XRPL Protocol Chains the Network ID should match the chosen peer port. + + - `xrpl-specific-idstring` is generated as described in the next section. + + +### 4.2.2. XRPL-specific-idstring Generation Method +XRPL DID MUST be unique within the XRPL network. + +`xrpl-specific-idstring` is the `AccountID` or the hex of `master public key` of the `DID` object's account. See [this](https://xrpl.org/accounts.html#address-encoding) for more details on XRPL public keys. + +Example: +A valid DID for an XRPL network may be +``` +did:xrpl:1:rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh +``` +or +``` +did:xrpl:1:0330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD020 +``` +The above DIDs are case-insensitive and will resolve to the same `DID` object. + +# 5. CRUD Operations +In this section we outline the following four CRUD operations for ``did:xrpl`` method. +- `Create` +- `Read` +- `Update` +- `Delete` + +## 5.1. DIDSet Transaction +The proposal introduces a new transaction type: **`DIDSet`** that can be used to: +- `Create` a new `DID` object, +- `Update` the existing `DID` object. + +### 5.1.1 Example **`DIDSet`** JSON +``` +{ + "TransactionType": "DIDSet", + "Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", + "Fee": "10", + "Sequence": 391, + "URI": "ipfs://bafybeigdyrzt5sfp7udm7hu76uh7y26nf4dfuylqabf3oclgtqy55fbzdi", + "Data": , + "SigningPubKey":"0330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD020", + ... + + } +``` +## Create +If the `DID` object associated with the `Account` does not exist, + - If both `URI` and `Data` fields are not present in the transaction, then transaction fails. + - Otherwise, a successful `DIDSet` transaction creates a new `DID` object with the following object ID: + + `SHA-512Half` of the following values, concatenated in order: + + - The `DID` space key (`0x0049`) + - The Account ID of the `Account`, i.e. rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh + +#### DID associated with this object is: +``` +did:xrpl:1:rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh +``` +or + +``` +did:xrpl:1:0330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD020 +``` + +### Implicit DID document +Some minimalistic use cases might only need signatures and simple authorization tokens, but don't need support for multiple keys or devices, complex organizational hierarchies and other advanced rights management features. + +To lower the entry level, we do not always require registering a `DID` by publishing a reference to or the DID Document on the ledger. If there's no explicitly registered `DID` found on the ledger then an implicit document is used instead as a default. Any update on this implicit document requires registering the `DID` object and applied changes on the ledger to be valid. + +For example, the implicit DID Document of `did:xrpl:1:0330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD020` enables only a single key 0330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD020 to authorize changes on the DID document or sign credentials in the name of the DID. + +## Update +If the `DID` object associated with the `Account` exists, + - If `URI`, `Data` and `DIDDocument` fields are not present, then transaction fails. + - Otherwise, a successful `DIDSet` transaction updates this object. + +### 5.1.2. Transaction-specific fields +| Field Name | Required? | JSON Type | Internal Type +| ---------------- |:-----------------: | :-------: | :---------------: +| `TransactionType`|:heavy_check_mark: | `string` | `UINT16` | + +Indicates the new transaction type **`DIDSet`**. The integer value is 40. + +--- +| Field Name | Required? | JSON Type | Internal Type +| ---------------- |:-----------------: | :-------: | :---------------: +| `Account` |:heavy_check_mark: | `string` | `AccountID` | + +Indicates the account which initiates the `DIDSet` transaction. This account MUST be a funded account on ledger. + +--- +| Field Name | Required? | JSON Type | Internal Type | +| --------------------- | :-----------------: | :-------: | :-------------: | +| `Fee` | :heavy_check_mark: | `number` | `Amount` | + +Indicates the fee that the account submitting this transaction is willing to pay. + +--- +| Field Name | Required? | JSON Type | Internal Type | +| -----------| :-----------------: | :-------: | :-------------: | +| `URI` | | `string` | `BLOB` | + +Indicates the `URI` field for this object. + +--- +| Field Name | Required? | JSON Type | Internal Type | +| -----------| :-----------------: | :-------: | :-------------: | +| `Data` | | `string` | `BLOB` | + +Indicates the `Data` field for this object. + +--- + +| Field Name | Required? | JSON Type | Internal Type +| -------------| :----------------: | :-------: | :-----------: +| `DIDDocument` | | `string` | `BLOB` | + +Indicates the DID document for this object. + +:notebook: If the `URI`, `Data`, or `DIDDocument` fields are missing, they will remain unchanged. However, if they contain an empty string, they will be deleted, otherwise, they will be updated. + +## 5.2. Read + +The initial step in utilizing a DID for an application may involve resolving the DID to access the underlying DID Document or attestations. This resolution process unveils the cryptographic material and service endpoints linked to the specific DID. + +In the case of XRPL DID, the `read` operation facilitates the resolution to the associated `DID` object. Upon successful resolution, applications can retrieve and utilize the relevant `URI` and/or `Data`, and/or `DIDDocument` fields contained within the `DID` object: + +Given the input DID for an account, follow these steps: + +- Retrieve the xrpl-specific-idstring of the DID. + +- If the xrpl-specific-idstring represents a public key: + + - Compute the Account ID using the method described [here](https://xrpl.org/accounts.html#address-encoding). + +- Retrieve the contents of the corresponding `DID` object in its raw format using the XRPL's [`account_objects`]( https://xrpl.org/account_objects.html#) command. Use the `account` field to specify the Account ID to retrieve all objects owned by that account, including `DID` object in the raw ledger format. Or optionally use the `type` field to filter the results by `ledger_entry` type, i.e. `DID` to retrieve the contents of just the `DID` object. + +### Example +Given the DID **did:xrpl:1:rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn**, do the following: +- Retrieve `rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn` +- Perform the `account_objects` method request to retrieve the contents of `DID` object: +``` +{ + "method": "account_objects", + "params": [ + { + "account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", + "ledger_index": "validated", + "type": "DID" + } + ] +} +``` + +A sample response to the above query might look like this: + +``` +200 OK +{ + "result": { + "account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", + "account_objects": [ + { + "URI":"ipfs://bafybeigdyrzt5sfp7udm7hu76uh7y26nf4dfuylqabf3oclgtqy55fbzdi" + } + ], + "validated": true + } +} + +``` +Upon receiving this response, an IPFS address (CAS) can be retrieved from the `URI` field. This address can then be resolved to retrieve the corresponding DID Document. + +:notebook: It is recommended that the applications implementing this method extend it to enable DID document fetching from the retrieved URI. + +Alternatively, one can use the [`ledger_entry`](https://xrpl.org/ledger_entry.html#ledger_entry) method to retrieve a single ledger entry (in this case `DID`) from the XRP Ledger in its raw format. + +## 5.3. DIDDelete Transaction +XRP ledger `DID` object owner or controller MAY want to delete the object. For this, we introduce a new transaction type called **`DIDDelete`**. A successful transaction will remove the ledger object and reduce the reserve requirement of the owner account. + +### 5.3.1. Example **`DIDDelete`** JSON +``` +{ + "TransactionType": "DIDDelete", + "Account": "rp4pqYgrTAtdPHuZd1ZQWxrzx45jxYcZex", + "Fee": "12", + "Sequence": 391, + "SigningPubKey":"0293A815C095DBA82FAC597A6BB9D338674DB93168156D84D18417AD509FFF5904", + "TxnSignature":"3044022011E9A7EE3C7AE9D202848390522E6840F7F3ED098CD13E...", + ... +} +``` +A successful `DIDDelete` transaction deletes the `DID` object corresponding to the `Account` + +### 5.3.2. Transaction-Specific Fields + +| Field Name | Required? | JSON Type | Internal Type +| ---------------- |:-----------------: | :-------: | :---------------: +| `TransactionType`|:heavy_check_mark: | `string` | `UINT16` | + +Indicates the new transaction type **`DIDDelete`**. The integer value is 41. + +--- +| Field Name | Required? | JSON Type | Internal Type | +| -----------| :-----------------: | :-------: | :-------------: | +| `Account` | :heavy_check_mark: | `string` | `AccountID` | + +Indicates the account that initiated the transaction. + +--- +| Field Name | Required? | JSON Type | Internal Type | +| -----------| :-----------------: | :-------: | :-------------: | +| `Fee` | :heavy_check_mark: | `string` | `Amount` | + +Indicates the fee that the account is willing to pay for this transaction. + + + +# 6. Privacy and Security Considerations +There are several security and privacy considerations that implementers would want to take into consideration when implementing this specification. + +## 6.1. Key Management + +The entity which controls the private key associated with the `DID` object, i.e. the XRPL `Account` also effectively controls the reference to the DID Document which the DID resolves to. Thus great care should be taken to ensure that the private key is kept private. Methods for ensuring key privacy are outside the scope of this document. + + +## 6.2. DID Document Public Profile +The DID document or other data associated with the XRPL DID's `URI` and/or `Data`, and/or `DIDDocument` fields can contain any content, though it is recommended that it conforms to the W3C DID Document and Verifiable Credentials (VC) specification. As anchored DIDs on XRPL can be resolved by anyone, care should be taken to only update to resolve DID Documents and data which DO NOT expose any sensitive personal information, or information which one may not wish to be public. DID documents should be limited to verification methods and service endpoints, and SHOULD not store any personal information. + +## 6.3. IPFS and Canonicity +IPFS allows anyone to store content publicly on the nodes in a distributed network. A common misconception is that anyone can edit content, however the content-addressability of IPFS means that this new edited content will have a different address to the original. While any entity can copy a DID Document anchored with an XRPL account's `URI`, they cannot change the document that a DID resolves to via the XRPL `account_objects` resolution unless they control the private key which created the corresponding `DID` object. + +For more, see [§ 10. Privacy Considerations](https://www.w3.org/TR/did-core/#privacy-considerations) in did-core. + +# 7. Implementations +A proposed implementation is in progress here: https://github.com/XRPLF/rippled/pull/4636/ + +# 8. Appendices +## Appendix 1. DID Document + +A DID is associated with a DID document. A DID document contains the necessary information to cryptographically verify the identity of the DID subject. W3C defines the [core properties](https://www.w3.org/TR/did-core/#core-properties) in a DID document, that describe relationships between the DID subject and the value of the property. For example, a DID document could contain cryptographic public keys such that the DID subject can use it to authenticate itself and proves its association with the DID. Usually, a DID document can be serialized to JSON representation or JSON-LD representation (see [DIDs v1.0]). + +Applications may choose one of the following for the DID document associated with a DID: +- Store a reference on the ledger in the `URI` field of `DID` object to the DID document stored in one or more parts on other decentralized storage networks such as IPFS or STORJ. +- Store a minimal DID document in the `Data` field of the `DID` object. +- Specify a minimal implicit DID document generated from the DID and other available public information. + +While not normative, a sample XRPL DID Document MAY look like: +``` +{ + "@context" : "https://w3id.org/did/v1", + "id" : "did:xrpl:1:rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", + "publicKey" : [ + { + "id" : "did:xrpl:1:rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn #keys-1", + "type" : ["CryptographicKey", "EcdsaKoblitzPublicKey"], + "curve" : "secp256k1", + "expires" : 15674657, + "publicKeyHex": "04f42987b7faee8b95e2c3a3345224f00e00dfc67ba882…." + } ] +} +``` + + W3C defines the [core properties](https://www.w3.org/TR/did-core/#core-properties) in a DID document, that describe relationships between the DID subject and the value of the property. + + +## Appendix 2. Universal Resolver +A Universal Resolver is an identifier resolver that works with any decentralized identifier system, including W3C DIDs. Refer [here](https://github.com/decentralized-identity/universal-resolver). A driver for XRPL DID method resolution will be added to universal resolver configurations to make it publicly accessible. + +## Appendix 3. Frequently Asked Questions +Q: Why use "Data" as the field name instead of a more specific term? + +A: The term "Data" was chosen to maintain flexibility and inclusivity within the specification. While some issuers refer to this information as "Attestations," others may use alternative terminology such as "public validations" or other terms. By using the term "Data," we aim to ensure that the specification remains adaptable to various implementations and promotes interoperability and broader applicability across the ecosystem of decentralized identity systems. From 83ad1d980898e3dd5af0c2a14efc067108926f2b Mon Sep 17 00:00:00 2001 From: Elliot Lee Date: Mon, 2 Oct 2023 13:40:16 -0700 Subject: [PATCH 17/17] Delete XLS-40/README.md --- XLS-40/README.md | 416 ----------------------------------------------- 1 file changed, 416 deletions(-) delete mode 100644 XLS-40/README.md diff --git a/XLS-40/README.md b/XLS-40/README.md deleted file mode 100644 index 58dbea13..00000000 --- a/XLS-40/README.md +++ /dev/null @@ -1,416 +0,0 @@ -
    
-Title:        Decentralized Identity on XRP Ledger
-Revision:     4 (2023-09-28)
-
-
Author: Aanchal Malhotra -Affiliation: Ripple - -
- -# 1. Abstract -Self-sovereign identity, defined as a lifetime portable digital identity that does not depend on any centralized authority, requires a new class of identifier that fulfills the following four requirements: persistence, global resolvability, cryptographic verifiability, and decentralization. [World Wide Web Consortium](https://www.w3.org/2022/07/pressrelease-did-rec.html.en) (W3C) standardized Decentralized Identifiers (DIDs) are a new type of identifier that enable verifiable, self-sovereign digital identity and are designed to be compatible with any distributed ledger or network. In the context of digital identities, W3C's standards for DIDs and Verifiable Credentials (VCs) are rapidly gaining traction, especially in blockchain-related domains. In this document we propose to implement native support for W3C DIDs on XRP Ledger. - -To this end, we specify the following on XRPL: -- A new `DID method` that describes: - - The format for XRP ledger DID, and - - Defines how XRP ledger DIDs are generated -- How to do `CRUD operations` on XRP ledger DIDs - -This specification conforms to the requirements specified in the [DID v1.0](https://www.w3.org/TR/did-core/) specification currently recommended by the W3C Credentials Community Group. - -# 2. Principles & Goals -## 2.1. Principles - -This proposal chooses to recommend W3C DID identity standard to satisfy the following first principles: - -- **Decentralized:** Requires no central issuing agency and functions effectively in Decentralized Finance. - -- **Persistent and Portable:** Inherently persistent and long-lived, not requiring the continued operation of any underlying organization and portable between different applications. - -- **Cryptographically Verifiable:** Based on cryptographic proofs rather than out-of-band trust. - -- **Universally Resolvable and Interoperable:** Open to any solution that recognizes the common W3C DID standards and requires no one specific software vendor implementation. - - -## 2.2. Goals & Non-Goals - -- This document aims to define DID identifier format for XRP ledger conformant to W3C DID standards that can be created and owned by any XRPL account holder, and specify definitions for DID methods to create, read, update and delete DID (data) that can be implemented by any service, wallet, or application. - -- This proposal is NOT intended as a competing decentralized identity standard; it aims to leverage existing (and emerging) decentralized identity standard proposed by W3C. - -- The proposal is motivated to enable **individual users** to create, and manage their decentralized identifiers while having complete control over the private keys and contents of the identity object. - -# 3. New On-Ledger Objects and Transactions -We propose one new ledger object and two new transaction types. -- **DID** is a new ledger object that is unique to an XRPL account and may contain a reference to, or the hash of, or the [W3C DID document](https://w3c-ccg.github.io/did-primer/#did-documents) itself associated with the corresponding DID. -- **DIDSet** is a new transaction type used to perform the following two operations: - - `Create` the new ledger object `DID` with `URI`, and/or `Data` fields, thus adding the required reserve towards the account that initiated the transaction. - - `Update` the mutable `URI` and `Data` fields of the `DID` object. -- **DIDDelete** is a new transaction type used to delete the `DID` object, thus reducing the reserve requirement towards the account that created the object. - -# 4. XRPL Decentralized Identifier (DID) Specification -In this section we specify the implementation details of W3C DID standard that are specific to XRP Ledger. - -## 4.1. The `DID` Object -We propose a new ledger object called **`DID`** that holds references to or data associated with a single DID. The `DID` object is created and updated using the `DIDSet` transaction and is deleted using the `DIDDelete` transaction. - -### 4.1.1. Object Fields -`DID` object may have the following required and optional fields. - -| Field Name | Required? | JSON Type | Internal Type -| ----------------- | :----------------: | :-------: | :-----------: -| `LedgerEntryType` | :heavy_check_mark: | `string` | `UINT16` | - -Identifies the type of ledger object. The proposal recommends the value `0x0049` as the reserved entry type. - ---- -| Field Name | Required? | JSON Type | Internal Type -| ----------------- | :----------------: | :-------: | :-----------: -| `PreviousTxnID` | :heavy_check_mark: | `string` | `Hash256` | - -The identifying hash of the transaction that most recently modified this object. - ---- -| Field Name | Required? | JSON Type | Internal Type -| ----------------- | :----------------: | :-------: | :-----------: -| `PreviousTxnLgrSeq` | :heavy_check_mark: | `number` | `UINT32` | - -The index of the ledger that contains the transaction that most recently modified this object. - ---- - - -| Field Name | Required? | JSON Type | Internal Type -| ----------------- | :----------------: | :-------: | :-----------: -| `URI` | | `string` | `BLOB` | - -`URI` specifies a Universal Resource Identifier, a.k.a. URI that SHOULD point to the corresponding DID document or to the data associated with the DID. This field could be an HTTP(S) URL or IPFS URI. The `URI` field is NOT checked for validity, but the field is limited to a maximum length of 256 bytes. - ---- -| Field Name | Required? | JSON Type | Internal Type -| -------------| :----------------: | :-------: | :-----------: -| `Data` | | `string` | `BLOB` | - -`Data` field SHOULD contain the public attestations of identity credentials associated with the DID. The `Data` field is NOT checked for validity, but the field is limited to a maximum length of 256 bytes. - ---- -| Field Name | Required? | JSON Type | Internal Type -| -------------| :----------------: | :-------: | :-----------: -| `DIDDocument` | | `string` | `BLOB` | - -`DIDDocument` field SHOULD contain the DID document per W3C standards associated with the DID. The field is NOT checked for validity, and is limited to a maximum length of 256 bytes. - -Note: -- Either `URI`, `Data` or `DIDDocument` field MUST be present to create and update the `DID` object. -- All `URI`, `Data` and `DIDDocument` fields MUST be absent to delete the `DID` object. - - -### 4.1.2. The `DID` Object ID Format -`DID` object may contain public data associated with the XRPL account's identity. This requires the `DID` to be: -- Unique in the XRPL namespace, and -- Uniquely associated with the XRPL account. - -We compute the `DID` object ID, a.k.a., `DIDID` as the `SHA-512Half` of the following values, concatenated in order: - -- The `DID` space key (`0x0049`) -- The Account ID - -### 4.1.3. Reserve Requirements -The account that creates the `DID` object will incur one owner reserve ~2 XRP at the time of writing this document. - -## 4.2. XRP Ledger DID Method Specification -In this section, we describe the DID method specification that conforms to the requirements specified in the DID specification currently published by the W3C Credentials Community Group. For more information about DIDs and DID method specifications, refer to the DID [Primer](https://github.com/WebOfTrustInfo/rwot5-boston/blob/master/topics-and-advance-readings/did-primer.md). - -### 4.2.1. XRP Ledger DID Scheme -The DID format as defined by W3C is as follows: -``` -"did:" method-name ":" method-specific-idstring -``` -We propose the following format for DIDs on XRPL: -``` -"did:xrpl": network-id: xrpl-specific-idstring -``` - -The components specific to the XRPL network are the following: - -- `method-name`: The `"xrpl"` namestring specifies that this is a DID for XRP Ledger. -A DID that uses this method MUST begin with the following prefix: `did:xrpl`. Per the DID specification, this string MUST be in lowercase. The remainder of the DID, after the prefix, is specified below. - -- `method-specific-idstring` is formed by `network-id` and `xrpl-specific-idstring` - - - `network-id`: `network-id` is a chain ID which is an identifier of XRP ledger networks. It specifies the underlying network instance where the `DID` is stored. Per [XLS-37d specification](https://github.com/XRPLF/rippled/pull/4418), in XRPL Protocol Chains the Network ID should match the chosen peer port. - - - `xrpl-specific-idstring` is generated as described in the next section. - - -### 4.2.2. XRPL-specific-idstring Generation Method -XRPL DID MUST be unique within the XRPL network. - -`xrpl-specific-idstring` is the `AccountID` or the hex of `master public key` of the `DID` object's account. See [this](https://xrpl.org/accounts.html#address-encoding) for more details on XRPL public keys. - -Example: -A valid DID for an XRPL network may be -``` -did:xrpl:1:rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh -``` -or -``` -did:xrpl:1:0330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD020 -``` -The above DIDs are case-insensitive and will resolve to the same `DID` object. - -# 5. CRUD Operations -In this section we outline the following four CRUD operations for ``did:xrpl`` method. -- `Create` -- `Read` -- `Update` -- `Delete` - -## 5.1. DIDSet Transaction -The proposal introduces a new transaction type: **`DIDSet`** that can be used to: -- `Create` a new `DID` object, -- `Update` the existing `DID` object. - -### 5.1.1 Example **`DIDSet`** JSON -``` -{ - "TransactionType": "DIDSet", - "Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", - "Fee": "10", - "Sequence": 391, - "URI": "ipfs://bafybeigdyrzt5sfp7udm7hu76uh7y26nf4dfuylqabf3oclgtqy55fbzdi", - "Data": , - "SigningPubKey":"0330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD020", - ... - - } -``` -## Create -If the `DID` object associated with the `Account` does not exist, - - If both `URI` and `Data` fields are not present in the transaction, then transaction fails. - - Otherwise, a successful `DIDSet` transaction creates a new `DID` object with the following object ID: - - `SHA-512Half` of the following values, concatenated in order: - - - The `DID` space key (`0x0049`) - - The Account ID of the `Account`, i.e. rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh - -#### DID associated with this object is: -``` -did:xrpl:1:rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh -``` -or - -``` -did:xrpl:1:0330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD020 -``` - -### Implicit DID document -Some minimalistic use cases might only need signatures and simple authorization tokens, but don't need support for multiple keys or devices, complex organizational hierarchies and other advanced rights management features. - -To lower the entry level, we do not always require registering a `DID` by publishing a reference to or the DID Document on the ledger. If there's no explicitly registered `DID` found on the ledger then an implicit document is used instead as a default. Any update on this implicit document requires registering the `DID` object and applied changes on the ledger to be valid. - -For example, the implicit DID Document of `did:xrpl:1:0330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD020` enables only a single key 0330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD020 to authorize changes on the DID document or sign credentials in the name of the DID. - -## Update -If the `DID` object associated with the `Account` exists, - - If `URI`, `Data` and `DIDDocument` fields are not present, then transaction fails. - - Otherwise, a successful `DIDSet` transaction updates this object. - -### 5.1.2. Transaction-specific fields -| Field Name | Required? | JSON Type | Internal Type -| ---------------- |:-----------------: | :-------: | :---------------: -| `TransactionType`|:heavy_check_mark: | `string` | `UINT16` | - -Indicates the new transaction type **`DIDSet`**. The integer value is 40. - ---- -| Field Name | Required? | JSON Type | Internal Type -| ---------------- |:-----------------: | :-------: | :---------------: -| `Account` |:heavy_check_mark: | `string` | `AccountID` | - -Indicates the account which initiates the `DIDSet` transaction. This account MUST be a funded account on ledger. - ---- -| Field Name | Required? | JSON Type | Internal Type | -| --------------------- | :-----------------: | :-------: | :-------------: | -| `Fee` | :heavy_check_mark: | `number` | `Amount` | - -Indicates the fee that the account submitting this transaction is willing to pay. - ---- -| Field Name | Required? | JSON Type | Internal Type | -| -----------| :-----------------: | :-------: | :-------------: | -| `URI` | | `string` | `BLOB` | - -Indicates the `URI` field for this object. - ---- -| Field Name | Required? | JSON Type | Internal Type | -| -----------| :-----------------: | :-------: | :-------------: | -| `Data` | | `string` | `BLOB` | - -Indicates the `Data` field for this object. - ---- - -| Field Name | Required? | JSON Type | Internal Type -| -------------| :----------------: | :-------: | :-----------: -| `DIDDocument` | | `string` | `BLOB` | - -Indicates the DID document for this object. - -:notebook: If the `URI`, `Data`, or `DIDDocument` fields are missing, they will remain unchanged. However, if they contain an empty string, they will be deleted, otherwise, they will be updated. - -## 5.2. Read - -The initial step in utilizing a DID for an application may involve resolving the DID to access the underlying DID Document or attestations. This resolution process unveils the cryptographic material and service endpoints linked to the specific DID. - -In the case of XRPL DID, the `read` operation facilitates the resolution to the associated `DID` object. Upon successful resolution, applications can retrieve and utilize the relevant `URI` and/or `Data`, and/or `DIDDocument` fields contained within the `DID` object: - -Given the input DID for an account, follow these steps: - -- Retrieve the xrpl-specific-idstring of the DID. - -- If the xrpl-specific-idstring represents a public key: - - - Compute the Account ID using the method described [here](https://xrpl.org/accounts.html#address-encoding). - -- Retrieve the contents of the corresponding `DID` object in its raw format using the XRPL's [`account_objects`]( https://xrpl.org/account_objects.html#) command. Use the `account` field to specify the Account ID to retrieve all objects owned by that account, including `DID` object in the raw ledger format. Or optionally use the `type` field to filter the results by `ledger_entry` type, i.e. `DID` to retrieve the contents of just the `DID` object. - -### Example -Given the DID **did:xrpl:1:rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn**, do the following: -- Retrieve `rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn` -- Perform the `account_objects` method request to retrieve the contents of `DID` object: -``` -{ - "method": "account_objects", - "params": [ - { - "account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", - "ledger_index": "validated", - "type": "DID" - } - ] -} -``` - -A sample response to the above query might look like this: - -``` -200 OK -{ - "result": { - "account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", - "account_objects": [ - { - "URI":"ipfs://bafybeigdyrzt5sfp7udm7hu76uh7y26nf4dfuylqabf3oclgtqy55fbzdi" - } - ], - "validated": true - } -} - -``` -Upon receiving this response, an IPFS address (CAS) can be retrieved from the `URI` field. This address can then be resolved to retrieve the corresponding DID Document. - -:notebook: It is recommended that the applications implementing this method extend it to enable DID document fetching from the retrieved URI. - -Alternatively, one can use the [`ledger_entry`](https://xrpl.org/ledger_entry.html#ledger_entry) method to retrieve a single ledger entry (in this case `DID`) from the XRP Ledger in its raw format. - -## 5.3. DIDDelete Transaction -XRP ledger `DID` object owner or controller MAY want to delete the object. For this, we introduce a new transaction type called **`DIDDelete`**. A successful transaction will remove the ledger object and reduce the reserve requirement of the owner account. - -### 5.3.1. Example **`DIDDelete`** JSON -``` -{ - "TransactionType": "DIDDelete", - "Account": "rp4pqYgrTAtdPHuZd1ZQWxrzx45jxYcZex", - "Fee": "12", - "Sequence": 391, - "SigningPubKey":"0293A815C095DBA82FAC597A6BB9D338674DB93168156D84D18417AD509FFF5904", - "TxnSignature":"3044022011E9A7EE3C7AE9D202848390522E6840F7F3ED098CD13E...", - ... -} -``` -A successful `DIDDelete` transaction deletes the `DID` object corresponding to the `Account` - -### 5.3.2. Transaction-Specific Fields - -| Field Name | Required? | JSON Type | Internal Type -| ---------------- |:-----------------: | :-------: | :---------------: -| `TransactionType`|:heavy_check_mark: | `string` | `UINT16` | - -Indicates the new transaction type **`DIDDelete`**. The integer value is 41. - ---- -| Field Name | Required? | JSON Type | Internal Type | -| -----------| :-----------------: | :-------: | :-------------: | -| `Account` | :heavy_check_mark: | `string` | `AccountID` | - -Indicates the account that initiated the transaction. - ---- -| Field Name | Required? | JSON Type | Internal Type | -| -----------| :-----------------: | :-------: | :-------------: | -| `Fee` | :heavy_check_mark: | `string` | `Amount` | - -Indicates the fee that the account is willing to pay for this transaction. - - - -# 6. Privacy and Security Considerations -There are several security and privacy considerations that implementers would want to take into consideration when implementing this specification. - -## 6.1. Key Management - -The entity which controls the private key associated with the `DID` object, i.e. the XRPL `Account` also effectively controls the reference to the DID Document which the DID resolves to. Thus great care should be taken to ensure that the private key is kept private. Methods for ensuring key privacy are outside the scope of this document. - - -## 6.2. DID Document Public Profile -The DID document or other data associated with the XRPL DID's `URI` and/or `Data`, and/or `DIDDocument` fields can contain any content, though it is recommended that it conforms to the W3C DID Document and Verifiable Credentials (VC) specification. As anchored DIDs on XRPL can be resolved by anyone, care should be taken to only update to resolve DID Documents and data which DO NOT expose any sensitive personal information, or information which one may not wish to be public. DID documents should be limited to verification methods and service endpoints, and SHOULD not store any personal information. - -## 6.3. IPFS and Canonicity -IPFS allows anyone to store content publicly on the nodes in a distributed network. A common misconception is that anyone can edit content, however the content-addressability of IPFS means that this new edited content will have a different address to the original. While any entity can copy a DID Document anchored with an XRPL account's `URI`, they cannot change the document that a DID resolves to via the XRPL `account_objects` resolution unless they control the private key which created the corresponding `DID` object. - -For more, see [§ 10. Privacy Considerations](https://www.w3.org/TR/did-core/#privacy-considerations) in did-core. - -# 7. Implementations -A proposed implementation is in progress here: https://github.com/XRPLF/rippled/pull/4636/ - -# 8. Appendices -## Appendix 1. DID Document - -A DID is associated with a DID document. A DID document contains the necessary information to cryptographically verify the identity of the DID subject. W3C defines the [core properties](https://www.w3.org/TR/did-core/#core-properties) in a DID document, that describe relationships between the DID subject and the value of the property. For example, a DID document could contain cryptographic public keys such that the DID subject can use it to authenticate itself and proves its association with the DID. Usually, a DID document can be serialized to JSON representation or JSON-LD representation (see [DIDs v1.0]). - -Applications may choose one of the following for the DID document associated with a DID: -- Store a reference on the ledger in the `URI` field of `DID` object to the DID document stored in one or more parts on other decentralized storage networks such as IPFS or STORJ. -- Store a minimal DID document in the `Data` field of the `DID` object. -- Specify a minimal implicit DID document generated from the DID and other available public information. - -While not normative, a sample XRPL DID Document MAY look like: -``` -{ - "@context" : "https://w3id.org/did/v1", - "id" : "did:xrpl:1:rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", - "publicKey" : [ - { - "id" : "did:xrpl:1:rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn #keys-1", - "type" : ["CryptographicKey", "EcdsaKoblitzPublicKey"], - "curve" : "secp256k1", - "expires" : 15674657, - "publicKeyHex": "04f42987b7faee8b95e2c3a3345224f00e00dfc67ba882…." - } ] -} -``` - - W3C defines the [core properties](https://www.w3.org/TR/did-core/#core-properties) in a DID document, that describe relationships between the DID subject and the value of the property. - - -## Appendix 2. Universal Resolver -A Universal Resolver is an identifier resolver that works with any decentralized identifier system, including W3C DIDs. Refer [here](https://github.com/decentralized-identity/universal-resolver). A driver for XRPL DID method resolution will be added to universal resolver configurations to make it publicly accessible. - -## Appendix 3. Frequently Asked Questions -Q: Why use "Data" as the field name instead of a more specific term? - -A: The term "Data" was chosen to maintain flexibility and inclusivity within the specification. While some issuers refer to this information as "Attestations," others may use alternative terminology such as "public validations" or other terms. By using the term "Data," we aim to ensure that the specification remains adaptable to various implementations and promotes interoperability and broader applicability across the ecosystem of decentralized identity systems.