From 7f69f550f973278bc417a0925f6e3750c4df59de Mon Sep 17 00:00:00 2001 From: Mayukha Vadari Date: Fri, 2 Aug 2024 12:19:01 -0400 Subject: [PATCH 01/26] XLS-0070d-simulate/README.md created from https://stackedit.io/ --- XLS-0070d-simulate/README.md | 573 +++++++++++++++++++++++++++++++++++ 1 file changed, 573 insertions(+) create mode 100644 XLS-0070d-simulate/README.md diff --git a/XLS-0070d-simulate/README.md b/XLS-0070d-simulate/README.md new file mode 100644 index 00000000..8f384ca9 --- /dev/null +++ b/XLS-0070d-simulate/README.md @@ -0,0 +1,573 @@ +
+Title:       On-Chain Credentials
+Revision:    3 (2024-07-23)
+
+Author:      Mayukha Vadari
+
+Affiliation: Ripple
+
+ +# On-Chain Credentials + +## Abstract + +The XRPL DID (Digital Identifier) amendment ([XLS-40](https://github.com/XRPLF/XRPL-Standards/tree/master/XLS-0040d-decentralized-identity)) empowers users to manage their digital identities on the XRP Ledger. While this amendment adds support for on-chain identity management and simplifies off-chain credential usage, maximizing blockchain technology's full potential for credential handling requires on-chain solutions. + +This document proposes a design to bridge this gap. It outlines the issuance, storage, and verification of credentials directly on the XRP Ledger, while still supporting the privacy needs of users. + +On-chain credentialing can streamline various processes within the XRPL ecosystem. For example, financial institutions can issue credentials on the XRP Ledger, attesting to a user's identity and compliance. This eliminates the need for repeated [KYC (Know Your Customer)](https://en.wikipedia.org/wiki/Know_your_customer) checks across different platforms, fostering a smoother user experience. By enabling secure credential management, this proposal unlocks the potential for a new wave of trust-based applications within the XRPL ecosystem. + +## 1. Overview + +This design adds support for creating, accepting, and deleting credentials. It also extends the existing [Deposit Authorization](https://xrpl.org/docs/concepts/accounts/depositauth) feature, allowing accounts to not only whitelist specific accounts, but also whitelist accounts with specific credentials. + +This proposal only supports blocking the interactions that Deposit Authorization supports, such as direct payments. However, future proposals could add support for credential-gating in other parts of the XRPL, such as AMMs or lending pools. + +We propose: +* Creating a `Credential` ledger object +* Modifying the `DepositPreauth` ledger object +* Modifying the `DepositPreauth` transaction +* Creating a `Credential` ledger object +* Creating a `CredentialCreate` transaction type +* Creating a `CredentialAccept` transaction type +* Creating a `CredentialDelete` transaction type + +This feature will require an amendment, tentatively titled `featureCredentialAuth`. + +### 1.1. Background: DIDs and Verifiable Credentials (VCs) + +A [verifiable credential](https://en.wikipedia.org/wiki/Verifiable_credentials) (VC), as defined by the [W3C specification](https://www.w3.org/TR/vc-data-model-2.0/), is a secure and tamper-evident way to represent information about a subject, such as an individual, organization, or even an IoT device. These credentials are issued by a trusted entity and can be verified by third parties without directly involving the issuer at all. + +For a clearer understanding of the relationship between [DIDs (Decentralized Identifiers)](https://en.wikipedia.org/wiki/Decentralized_identifier) and VCs, a real-world example is considered. A DID serves as a unique identifier for an entity, similar to a fingerprint or a photo of a person (their physical characteristics). In contrast, a VC acts as a verifiable piece of information associated with that DID, much like a driver's license or passport. When a third party needs to verify an identity claim, they can examine the VC presented by the entity and ensure it aligns with the corresponding DID (such as comparing the photo on a driver's license to the physical characteristics of the person to whom it supposedly belongs). + +### 1.2. Terminology + +* **Credential**: A representation of one or more assertions made by an issuer. For example, a passport is a representation of the assertion that a person is a citizen of a given country. +* **Issuer**: The account that creates (issues) the credential. For example, a passport is issued by a country's government. +* **Subject**: The account that the credential is issued to. For example, a passport is issued to a specific person. +* **Whitelist**: A list of accounts that are allowed to do a given action, or (if used as a verb) the action of adding an account to said list. +* **Preauthorization**: Essentially the same thing as whitelisting. + +*Note: These definitions do not directly match the definitions listed in the [W3C Verifiable Credentials spec](https://www.w3.org/TR/vc-data-model-2.0/#terminology). These terms are used in a slightly different way in the context of this spec.* + +### 1.3. Basic Flow + +In this scenario, an authorizer/verifier account, Verity, is a regulated entity wants to ensure that she is only interacting with properly KYC'd accounts. + +* Verity sets up her account such that she only wants to interact with properly KYC'd accounts. He trusts Isabel, a credential issuer, to properly vet accounts and issue credentials attesting to that. +* Alice, who wants to interact with Verity's account, submits her KYC documents to Isabel off-chain. Isabel creates a credential attesting to her trustworthiness on-chain. +* Alice accepts the credential, making it a valid credential. +* Alice can now interact with/send funds to Verity. + +## 2. On-Ledger Object: `Credential` + +This object will be an on-chain representation of a credential, while ensuring that any sensitive details are kept off-chain, to protect the subject's privacy. + +### 2.1. Fields + +| Field Name | Required? | JSON Type | Internal Type | Description | +|------------|-----------|-----------|---------------|-------------| +|`LedgerEntryType`| ✔️|`string`|`UInt16`|The ledger object's type (`Credential`).| +|`Flags`| ✔️|`number`|`UInt32`|Flag values associated with this object.| +|`Subject`| ✔️|`string`|`AccountID`|The account that the credential is for.| +|`Issuer`| ✔️|`string`|`AccountID`|The issuer of the credential.| +|`CredentialType`| ✔️|`string`|`Blob`|A (hex-encoded) value to identify the type of credential from the issuer.| +|`Expiration`| |`number`|`UInt32`|Optional credential expiration.| +|`URI`| |`string`|`Blob`|Optional additional data about the credential (such as a link to the VC document).| +|`OwnerNode`|✔️|`string`|`UInt64`|A hint indicating which page of the sender's owner directory links to this object, in case the directory consists of multiple pages. Note: The object does not contain a direct link to the owner directory containing it, since that value can be derived from the `Account.PreviousTxnID`.| +|`PreviousTxnID`|✔️|`string`|`Hash256`|The identifying hash of the transaction that most recently modified this object.| +|`PreviousTxnLgrSeqNumber`|✔️|`number`|`UInt32`|The index of the ledger that contains the transaction that most recently modified this object.| + +#### 2.1.1. Object ID + +The ID of this object will be a hash that incorporates the `Subject`, `Issuer`, and `CredentialType` fields, combined with a unique space key for `Credential` objects, which will be defined during implementation. + +#### 2.1.2. `Flags` +| Flag Name | Flag Value | +|-----------|------------| +|`lsfAccepted`|`0x00010000`| + +`lsfAccepted` is on if the subject of the credential has accepted the credential. If it is off, the issuer has the reserve burden; if it is on, the burden moves to the subject. + +#### 2.1.3. `CredentialType` + +This value is similar to the NFT `Taxon` value, where the value's meaning will be decided by the issuer. It may be the same as a claim in a VC, but could also represent a subset of such a claim. + +### 2.2. Account Deletion + +The `Credential` object is not a [deletion blocker](https://xrpl.org/docs/concepts/accounts/deleting-accounts/#requirements). + +## 3. On-Ledger Object: `DepositPreauth` + +The `DepositPreauth` object tracks a preauthorization from one account to another. This object already exists on the XRPL, but is being extended as a part of this spec to also support credential preauthorization. + +### 3.1. Fields +
+ + +As a reference, [here](https://xrpl.org/docs/references/protocol/ledger-data/ledger-entry-types/depositpreauth/#depositpreauth-fields) are the existing fields for the `DepositPreauth` object. + + +| Field Name | Required? | JSON Type | Internal Type | Description | +|------------|-----------|-----------|---------------|-------------| +|`Account`|✔️|`string`|`AccountID`|The account that granted the preauthorization (the destination of the preauthorized payments).| +|`Authorize`|✔️|`string`|`AccountID`|The account that received the preauthorization (the sender of the preauthorized payments).| +|`LedgerEntryType`|✔️|`string`|`UInt16`|The value `0x0070`, mapped to the string `"DepositPreauth"`, indicates that this is a `DepositPreauth` object.| +|`OwnerNode`|✔️|`string`|`UInt64`|A hint indicating which page of the sender's owner directory links to this object, in case the directory consists of multiple pages. Note: The object does not contain a direct link to the owner directory containing it, since that value can be derived from the `Account.PreviousTxnID`.| +|`PreviousTxnID`|✔️|`string`|`Hash256`|The identifying hash of the transaction that most recently modified this object.| +|`PreviousTxnLgrSeqNumber`|✔️|`number`|`UInt32`|The index of the ledger that contains the transaction that most recently modified this object.| +
+ +We propose these modifications: + +| Field Name | Required? | JSON Type | Internal Type | Description | +|------------|-----------|-----------|---------------|-------------| +|`Authorize`| |`string`|`AccountID`|The account that received the preauthorization. (The sender of the preauthorized payments.)| +|`AuthorizeCredentials`| |`array`|`STArray`|The credential that received the preauthorization. (Any account with this credential can send preauthorized payments).| + +#### 3.1.1. Object ID + +The ID of this object will be either a hash of the `Account` and `Authorize` fields (as it currently is), or a hash of the `Account` and the contents of `AuthorizeCredentials` fields, combined with the unique space key for `DepositAuth` objects: `0x0070`. + +#### 3.1.2. `Authorize` + +This field is now optional, and a valid `DepositPreauth` object must either have the `Authorize` field or the `AuthorizeCredentials` field. + +#### 3.1.3. `AuthorizeCredentials` + +This field is an array of inner objects. The contents of these inner objects determine the credential(s) that are accepted. + +If more than one credential is included in the list, all of those credentials must be included (effectively ANDing them together). + +The list has a maximum size of 8 credentials. + +| Field Name | Required? | JSON Type | Internal Type | Description | +|------------|-----------|-----------|---------------|-------------| +|`Issuer`|✔️|`string`|`AccountID`|The issuer of the credential.| +|`CredentialType`|✔️|`string`|`Blob`|A (hex-encoded) value to identify the type of credential from the issuer.| + +## 4. Transaction: `DepositPreauth` + +This transaction currently creates and deletes `DepositPreauth` objects, thereby whitelisting and unwhitelisting accounts. + +This spec extends that functionality to also support whitelisting and unwhitelisting credentials. + +### 4.1. Fields + +As a reference, [here](https://xrpl.org/docs/references/protocol/transactions/types/depositpreauth/#depositpreauth-fields) are the existing fields for the `DepositPreauth` transaction: + +| Field Name | Required? | JSON Type | Internal Type | Description | +|------------|-----------|-----------|---------------|-------------| +|`Authorize`| |`string`|`AccountID`|The XRP Ledger address of the sender to preauthorize. | +|`Unauthorize` | |`string`|`AccountID`|The XRP Ledger address of a sender whose preauthorization should be revoked.| + +This proposal adds two new fields: +| Field Name | Required? | JSON Type | Internal Type | Description | +|------------|-----------|-----------|---------------|-------------| +|`AuthorizeCredentials`| |`array`|`STArray`|The credential(s) to preauthorize. | +|`UnauthorizeCredentials` | |`array`|`STArray`|The credential(s) whose preauthorization should be revoked.| + +#### 4.1.1. `AuthorizeCredentials` and `UnauthorizeCredentials` + +These fields follow the same rules outlined in section 3.1.3 for the `Credential` object's `AuthorizeCredentials` field. + +### 4.2. Failure Conditions +* Existing failure conditions for `DepositPreauth` will still be obeyed. +* None or more than one of `Authorize`, `Unauthorize`, `AuthorizeCredentials`, and `UnauthorizeCredentials` are included (i.e. there must be exactly one of these fields included). +* The issuer of the credential doesn't exist. +* If `UnauthorizeCredentials` is included in the transaction, the credential(s) are not currently authorized. +* If `AuthorizeCredentials` is included in the transaction: + * The credential(s) are already authorized. + * The account doesn't have enough reserve for the object. + * The array is too long (i.e. has more than 8 credentials). + * The array is empty (i.e. has no credentials). + +### 4.3. State Changes + +If the transaction is successful: +* The `DepositPreauth` object is created or deleted. + +## 5. Transaction: `CredentialCreate` + +This transaction creates a `Credential` object. + +There are two possible methods of doing so: +* The issuer submits this transaction, and `CredentialAccept` is used for the subject to accept the transaction. +* The credential data is passed off-chain from the issuer to the subject. The subject then submits the credential themselves, alongside an issuer signature, to the ledger. + +### 5.1. Fields + +| Field Name | Required? | JSON Type | Internal Type | Description | +|------------|-----------|-----------|---------------|-------------| +|`TransactionType`| ✔️|`string`|`UInt16`|The transaction type (`CredentialCreate`).| +|`Account`| ✔️|`string`|`AccountID`|The subject or issuer of the credential.| +|`Subject`| |`string`|`AccountID`|The subject of the credential.| +|`Issuer`| |`string`|`AccountID`|The issuer of the credential.| +|`CredentialType`|✔️|`string`|`Blob`|A (hex-encoded) value to identify the type of credential from the issuer.| +|`Signature`| |`string`|`Blob`|A signature from the issuer attesting to the credential.| +|`Expiration`| |`number`|`UInt32`|Optional credential expiration.| +|`URI`| |`string`|`Blob`|Optional additional data about the credential (such as a link to the VC document).| + +#### 5.1.1. `Subject` and `Issuer` + +Only one of these two fields must be specified. If `Subject` is specified, `Account` is the issuer. If `Issuer` is specified, `Account` is the subject. + +#### 5.1.2. `Signature` + +If the subject is submitting the account, a signature must be included from the issuer attesting to the credential. This signature will sign a simple JSON that looks something like this: +```typescript +{ + Issuer: "rISABEL......", + Subject: "rALICE.......", + CredentialType: "123ABC", +} +``` + +### 5.2. Failure Conditions + +* Both or neither `Subject` and `Issuer` are specified (i.e. there must be only one of the two fields). +* The account in `Subject`/`Issuer` doesn't exist. +* `Issuer` is included but `Signature` is not. +* The time in `Expiration` is in the past. +* The `URI` field is too long (limit 256 bytes). +* The account doesn't have enough reserve for the object. + +### 5.3. State Changes + +If the transaction is successful: +* The `Credential` object is created. +* If `Issuer` == `Account`, then the `lsfAccepted` flag is enabled. + +## 6. Transaction: `CredentialAccept` + +This transaction transfers a credential from the `Issuer` to the `Account`. It is not a valid credential until it has been transferred. + +### 6.1. Fields + +| Field Name | Required? | JSON Type | Internal Type | Description | +|------------|-----------|-----------|---------------|-------------| +|`TransactionType`| ✔️|`string`|`UInt16`|The transaction type (`CredentialAccept`).| +|`Account`| ✔️|`string`|`AccountID`|The subject of the credential.| +|`Issuer`| ✔️|`string`|`AccountID`|The issuer of the credential.| +|`CredentialType`|✔️|`string`|`Blob`|A (hex-encoded) value to identify the type of credential from the issuer.| + +### 6.2. Failure Conditions + +* The account in `Account` or `Issuer` doesn't exist. +* There is no valid credential described by the fields of the transaction. +* The credential has already been accepted. +* The `Account` doesn't have enough reserve for the object. + +### 6.3. State Changes + +If the transaction is successful: +* The `lsfAccepted` flag is turned on in the credential. +* The `Credential` object is moved from the issuer's owner directory to the subject's. + +## 7. Transaction: `CredentialDelete` + +This transaction deletes a `Credential` object. + +It can be executed by: +* The issuer, anytime. +* The account, anytime. +* Anyone, after the expiration time is up. + +### 7.1. Fields + +| Field Name | Required? | JSON Type | Internal Type | Description | +|------------|-----------|-----------|---------------|-------------| +|`TransactionType`| ✔️|`string`|`UInt16`|The transaction type (`CredentialDelete`).| +|`Account`| ✔️|`string`|`AccountID`|The transaction submitter.| +|`Subject`| |`string`|`AccountID`|The person that the credential is for. If omitted, `Account` is assumed to be the subject.| +|`Issuer`| |`string`|`AccountID`|The issuer of the credential. If omitted, `Account` is assumed to be the issuer.| +|`CredentialType`|✔️|`string`|`Blob`|A (hex-encoded) value to identify the type of credential from the issuer.| + +### 7.2. Failure Conditions + +* The credential described by the `Subject`, `Issuer`, and `CredentialType` fields doesn't exist. +* The `Account` isn't the issuer or account, and the expiration hasn't passed. + +### 7.3. State Changes + +If the transaction is successful: +* The `Credential` object is deleted. + +## 8. Transactions: Common Fields + +### 8.1. Fields + +As a reference, [here](https://xrpl.org/docs/references/protocol/transactions/common-fields/) are the fields that all transactions currently have. + + + +| Field Name | Required? | JSON Type | Internal Type | +|------------|-----------|-----------|---------------| +|`CredentialIDs`| ✔️|`array`|`Vector256`|Credential(s) to attach to the transaction.| + +Transactions that accept this field: +* Basically anything with a `Destination` field (like a payment) or something that has to be accepted by the destination (like an escrow/check). + +### 8.2. Failure Conditions + +* Any of the `CredentialIDs` isn't an object that exists. +* Any of the `CredentialIDs` isn't a `Credential` object. +* Any of the `CredentialIDs` is an expired `Credential` object. +* `CredentialIDs` is included, but the destination doesn't have Deposit Authorization set up, or the transaction doesn't have a destination (e.g. `AccountSet`). +* The `CredentialIDs` are not authorized by the destination. + +Note: the transaction will still fail if too many credentials are included. The exact list must be provided. + +### 8.3. State Changes + +* If the credential isn't valid, it gets blocked. +* If the credential is expired, it is deleted. + +## 9. RPC: `deposit_authorized` + +The [`deposit_authorized` RPC method](https://xrpl.org/deposit_authorized.html) already exists on the XRPL. This proposal suggests some modifications to also support permissioned DEX domains. + +### 9.1. Request Fields + +| Field Name | Required? | JSON Type | Description | +|------------|-----------|-----------|-------------| +|`source_account`|✔️|`string`|The sender of a possible payment.| +|`destination_account`|✔️|`string`|The recipient of a possible payment.| +|`ledger_hash`| |`string`|A 20-byte hex string for the ledger version to use. | +|`ledger_index`| |`string` or `number`|The ledger index of the ledger to use, or a shortcut string to choose a ledger automatically.| + +This proposal puts forward the following addition: + +| Field Name | Required? | JSON Type | Description | +|------------|-----------|-----------|-------------| +|`credentials`| |`array`|The object IDs of `Credential` objects. If this field is included, then the credential will be taken into account when analyzing whether the sender can send funds to the destination.| + +### 9.2. Response Fields + +| Field Name | Always Present? | JSON Type | Description | +|------------|-----------------|-----------|-------------| +|`deposit_authorized`|✔️|`boolean`|Whether the specified source account is authorized to send payments directly to the destination account. If true, either the destination account does not require deposit authorization or the source account is preauthorized.| +|`destination_account`|✔️|`string`|The destination account specified in the request.| +|`source_account`|✔️|`string`|The source account specified in the request.| +|`ledger_hash`| |`string`|The identifying hash of the ledger that was used to generate this response.| +|`ledger_index`| |`number`|The ledger index of the ledger version that was used to generate this response.| +|`ledger_current_index`| |`number`|The ledger index of the current in-progress ledger version, which was used to generate this response.| +|`validated`| |`boolean`|If true, the information comes from a validated ledger version.| + +## 10. Compliance with W3C Spec + +This proposal prioritizes interoperability with the [W3C Verifiable Credential (VC) spec](https://www.w3.org/TR/vc-data-model/). The existing verification flow for XRPL-based Verifiable Credentials remains the primary method: +1. **DID Resolution:** Verifiers access the DID document from the DID ID (e.g., `did:xrpl:r....`). This document is stored in the account's [DID object](https://xrpl.org/docs/references/protocol/ledger-data/ledger-entry-types/did). +2. **VC Access:** The DID document provides a link to the relevant Verifiable Credentials. +3. **VC Verification:** Based on access permissions, verifiers can then view and verify the retrieved VCs. + +However, this proposal introduces an optional enhancement. Within the `Credential` object, the `URI` field can also point to the VC. It's important to note that this pointer is entirely optional, and the core verification process using DID resolution will still be the primary method for XRPL credential verification. + +It is recommended that anyone who holds a credential also have a DID object, to increase compliance with the W3C VC spec. + +Note that the issuer of the on-chain `Credential` does not have to be the same as the issuer of the VC, and the on-chain object can instead essentially serve as an on-chain attestation from the issuer for the VC. + +## 11. Invariants + +### 11.1. Reserves + +The burden of reserve should be with the issuer, and the credential should be in the issuer's owner directory, if the `lsfAccepted` flag is off. The burden of reserve should be with the subject and the credential should be in the subject's owner directory, if the `lsfAccepted` flag is on. + +### 11.2. The `DepositPreauth` Object + +A `DepositPreauth` ledger object always has exactly one of the `Authorize` field and the `AuthorizeCredentials` field. + +If the `AuthorizeCredentials` field is included, the array contains between 1 and 8 credentials. + +## 12. Examples + +In this example, a trusted issuer, Isabel, is issuing a credential that indicates that Alice is KYC'd. Verity is setting up her account to only interact with accounts that Isabel has attested to being properly KYC'd. + +For ease of reading, some of the common transaction fields, such as signatures and public keys, have been left out of this example. + +### 12.1. `CredentialCreate` + +Isabel creates the credential for Alice, after confirming her KYC status off-chain. + +```typescript +{ + TransactionType: "CredentialCreate", + Account: "rISABEL......", + Subject: "rALICE.......", + CredentialType: "4B5943", // "KYC" in hex + Expiration: 789004799, // the end of the year + URI: "isabel.com/credentials/kyc/alice" // This will be converted into hex +} +``` + +### 12.2. The `Credential` Object + +This is the object created by the `CredentialCreate` transaction. + +```typescript +{ + LedgerEntryType: "Credential", + Flags: 0, + Subject: "rALICE.......", + Issuer: "rISABEL......", + CredentialType: "123ABC", + Expiration: 789004799, // the end of the year + URI: "isabel.com/credentials/kyc/alice" // This will be converted into hex +} +``` + +### 12.3. `CredentialAccept` + +Alice accepts the credential, thereby making it valid. + +```typescript +{ + TransactionType: "CredentialAccept", + Account: "rALICE.......", + Issuer: "rISABEL......", + CredentialType: "123ABC" +} +``` + +### 12.4. `DepositPreauth` + +Verity sets up her account to only interact with accounts that Isabel has KYC'd. + +```typescript +{ + TransactionType: "DepositPreauth", + Account: "rVERITY......", + AuthorizeCredentials: [ + { + Credential: { + Issuer: "rISABEL......", + CredentialType: "4B5943" + } + } + ] +} +``` + +### 12.5. Payments + +This transaction will succeed, since Alice has attached the authorized credential from Isabel. + +```typescript +{ + TransactionType: "Payment", + Account: "rALICE......", + Destination: "rVERITY......", + Amount: "10000000", + CredentialIDs: ["DD40031C6C21164E7673...17D467CEEE9"] +} +``` + +This transaction will fail, since Alice has not attached the authorized credential from Isabel. This is akin to trying to go through airport security without a form of ID. + +```typescript +{ + TransactionType: "Payment", + Account: "rALICE......", + Destination: "rVERITY......", + Amount: "10000000" +} +``` + +This transaction will fail, since the attached credential isn't Bob's. + +```typescript +{ + TransactionType: "Payment", + Account: "rBOB......", + Destination: "rVERITY......", + Amount: "10000000", + CredentialIDs: ["DD40031C6C21164E7673...17D467CEEE9"] +} +``` + +This transaction will fail, since Bob doesn't have a valid credential from Isabel. + +```typescript +{ + TransactionType: "Payment", + Account: "rBOB......", + Destination: "rVERITY......", + Amount: "10000000" +} +``` + +This transaction will fail, since Bob doesn't have Deposit Authorization set up. + +```typescript +{ + TransactionType: "Payment", + Account: "rALICE......", + Destination: "rBOB......", + Amount: "10000000", + CredentialIDs: ["DD40031C6C21164E7673...17D467CEEE9"] +} +``` + +## 13. Security + +### 13.1. Trust Assumptions + +You need to trust the issuer to only be issuing valid credentials, and to not delete a credential without a legitimate reason. + +### 13.2. Data Privacy + +No private data needs to be stored on-chain (e.g. all the KYC data). The actual VC can still be stored off-chain. It could be stored at a link in the `URI` field. + +# Appendix + +## Appendix A: FAQ + +### A.1: Do I have to only use credentials with the Deposit Authorization feature? Can I also use them for off-chain purposes? + +You can use credentials for any purpose you'd like, not just for Deposit Authorization. + +### A.2: Do I need to use credentials for VCs or can I use them for other things? + +You can use credentials for any purpose you'd like. The recommended usecase is VCs, but there are plenty of other usecases for them. + +### A.3: Why not use NFTs instead, with a certain issuer-taxon combo and the `tfTransferable` flag unset? + +Using NFTs instead wouldn't be as elegant, since it means that the NFT has to follow a specific format. It would make more sense for an off-ledger use-case, not directly on-ledger. In addition, an NFT serves different needs - e.g. NFTs don't have an expiration. + +### A.4: Can an issuer issue a credential for themselves? + +Yes. + +### A.5: Can an issuer edit the details of a credential once it's created? + +No, it would have to be deleted and recreated. This is similar to needing to get a new card if your license/passport expires. If the `Subject`, `Issuer`, and `CredentialType` stay the same, though, the object will still have the same ID as before. + +### A.6: Why do I need to include the `CredentialIDs` field in my transaction? Shouldn't the XRPL be able to figure out whether I have a valid credential automatically? + +There is no way for the XRPL to iterate through just the list of credentials an account has; it can only iterate through the entire list of account objects. This is an unbounded list of objects (it could be millions of objects). Even just the list of accepted credentials could theoretically be millions of objects long. It could cause serious performance issues if the system had to iterate through the whole list. + +It's much faster to have the credential ID included - it's easy to make sure that that's a valid credential, and check that it's an authorized credential. + +### A.7: Can a credential issuer delete their account? + +Yes, even if they still have issued credentials in existence. + +### A.8: Does a credential issue have to have an on-chain account? + +No, though they must have a valid keypair. If the second method of creating a credential is used (via a signature from the issuer), the issuer can still attest to a credential without having to have an account on-chain. This is to ensure closer compliance with the W3C Verifiable Credentials spec (see section 9). + +### A.9: How do I get a list of credentials that an issuer has issued? + +The answer to that question is still being investigated. One option would be a Clio API. + +### A.10: Can I edit the list of credentials stored in `AuthorizeCredentials`? + +No, you have to delete the `DepositPreauth` object and recreate it with the new list. + +### A.11: Does the list of credentials in `AuthorizeCredentials` _have_ to be AND-ed together? Can I instead use it as an OR list (i.e. only provide one of the credentials instead of all)? Or some complex combination? + +No. You can OR credential(s) by putting them in separate `DepositPreauth` objects. For performance reasons, it is much easier to do a credential lookup if you need to have all of the credentials. Otherwise, you'd have to search the whole list. In addition, people who need to use this feature will likely not find the object reserve cost-prohibitive. + +### A.12: Why are `CredentialCreate` and `CredentialDelete` separate transactions? + +It's easier and clearer to have those be separate operations. From 18672eb45ad3de27ee5726841578f2a7a2efd9bf Mon Sep 17 00:00:00 2001 From: Mayukha Vadari Date: Fri, 2 Aug 2024 12:20:18 -0400 Subject: [PATCH 02/26] XLS-0070d-simulate/README.md updated from https://stackedit.io/ --- XLS-0070d-simulate/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/XLS-0070d-simulate/README.md b/XLS-0070d-simulate/README.md index 8f384ca9..8cb0ee1d 100644 --- a/XLS-0070d-simulate/README.md +++ b/XLS-0070d-simulate/README.md @@ -1,6 +1,6 @@
 Title:       On-Chain Credentials
-Revision:    3 (2024-07-23)
+Revision:    3
 
 Author:      Mayukha Vadari
 

From f7c95fbb1d1fc88224e4be3b2d42075eb0118f99 Mon Sep 17 00:00:00 2001
From: Mayukha Vadari 
Date: Fri, 2 Aug 2024 16:02:53 -0400
Subject: [PATCH 03/26] XLS-0070d-credentials/README.md created from
 https://stackedit.io/

---
 XLS-0070d-credentials/README.md | 573 ++++++++++++++++++++++++++++++++
 1 file changed, 573 insertions(+)
 create mode 100644 XLS-0070d-credentials/README.md

diff --git a/XLS-0070d-credentials/README.md b/XLS-0070d-credentials/README.md
new file mode 100644
index 00000000..8cb0ee1d
--- /dev/null
+++ b/XLS-0070d-credentials/README.md
@@ -0,0 +1,573 @@
+
+Title:       On-Chain Credentials
+Revision:    3
+
+Author:      Mayukha Vadari
+
+Affiliation: Ripple
+
+ +# On-Chain Credentials + +## Abstract + +The XRPL DID (Digital Identifier) amendment ([XLS-40](https://github.com/XRPLF/XRPL-Standards/tree/master/XLS-0040d-decentralized-identity)) empowers users to manage their digital identities on the XRP Ledger. While this amendment adds support for on-chain identity management and simplifies off-chain credential usage, maximizing blockchain technology's full potential for credential handling requires on-chain solutions. + +This document proposes a design to bridge this gap. It outlines the issuance, storage, and verification of credentials directly on the XRP Ledger, while still supporting the privacy needs of users. + +On-chain credentialing can streamline various processes within the XRPL ecosystem. For example, financial institutions can issue credentials on the XRP Ledger, attesting to a user's identity and compliance. This eliminates the need for repeated [KYC (Know Your Customer)](https://en.wikipedia.org/wiki/Know_your_customer) checks across different platforms, fostering a smoother user experience. By enabling secure credential management, this proposal unlocks the potential for a new wave of trust-based applications within the XRPL ecosystem. + +## 1. Overview + +This design adds support for creating, accepting, and deleting credentials. It also extends the existing [Deposit Authorization](https://xrpl.org/docs/concepts/accounts/depositauth) feature, allowing accounts to not only whitelist specific accounts, but also whitelist accounts with specific credentials. + +This proposal only supports blocking the interactions that Deposit Authorization supports, such as direct payments. However, future proposals could add support for credential-gating in other parts of the XRPL, such as AMMs or lending pools. + +We propose: +* Creating a `Credential` ledger object +* Modifying the `DepositPreauth` ledger object +* Modifying the `DepositPreauth` transaction +* Creating a `Credential` ledger object +* Creating a `CredentialCreate` transaction type +* Creating a `CredentialAccept` transaction type +* Creating a `CredentialDelete` transaction type + +This feature will require an amendment, tentatively titled `featureCredentialAuth`. + +### 1.1. Background: DIDs and Verifiable Credentials (VCs) + +A [verifiable credential](https://en.wikipedia.org/wiki/Verifiable_credentials) (VC), as defined by the [W3C specification](https://www.w3.org/TR/vc-data-model-2.0/), is a secure and tamper-evident way to represent information about a subject, such as an individual, organization, or even an IoT device. These credentials are issued by a trusted entity and can be verified by third parties without directly involving the issuer at all. + +For a clearer understanding of the relationship between [DIDs (Decentralized Identifiers)](https://en.wikipedia.org/wiki/Decentralized_identifier) and VCs, a real-world example is considered. A DID serves as a unique identifier for an entity, similar to a fingerprint or a photo of a person (their physical characteristics). In contrast, a VC acts as a verifiable piece of information associated with that DID, much like a driver's license or passport. When a third party needs to verify an identity claim, they can examine the VC presented by the entity and ensure it aligns with the corresponding DID (such as comparing the photo on a driver's license to the physical characteristics of the person to whom it supposedly belongs). + +### 1.2. Terminology + +* **Credential**: A representation of one or more assertions made by an issuer. For example, a passport is a representation of the assertion that a person is a citizen of a given country. +* **Issuer**: The account that creates (issues) the credential. For example, a passport is issued by a country's government. +* **Subject**: The account that the credential is issued to. For example, a passport is issued to a specific person. +* **Whitelist**: A list of accounts that are allowed to do a given action, or (if used as a verb) the action of adding an account to said list. +* **Preauthorization**: Essentially the same thing as whitelisting. + +*Note: These definitions do not directly match the definitions listed in the [W3C Verifiable Credentials spec](https://www.w3.org/TR/vc-data-model-2.0/#terminology). These terms are used in a slightly different way in the context of this spec.* + +### 1.3. Basic Flow + +In this scenario, an authorizer/verifier account, Verity, is a regulated entity wants to ensure that she is only interacting with properly KYC'd accounts. + +* Verity sets up her account such that she only wants to interact with properly KYC'd accounts. He trusts Isabel, a credential issuer, to properly vet accounts and issue credentials attesting to that. +* Alice, who wants to interact with Verity's account, submits her KYC documents to Isabel off-chain. Isabel creates a credential attesting to her trustworthiness on-chain. +* Alice accepts the credential, making it a valid credential. +* Alice can now interact with/send funds to Verity. + +## 2. On-Ledger Object: `Credential` + +This object will be an on-chain representation of a credential, while ensuring that any sensitive details are kept off-chain, to protect the subject's privacy. + +### 2.1. Fields + +| Field Name | Required? | JSON Type | Internal Type | Description | +|------------|-----------|-----------|---------------|-------------| +|`LedgerEntryType`| ✔️|`string`|`UInt16`|The ledger object's type (`Credential`).| +|`Flags`| ✔️|`number`|`UInt32`|Flag values associated with this object.| +|`Subject`| ✔️|`string`|`AccountID`|The account that the credential is for.| +|`Issuer`| ✔️|`string`|`AccountID`|The issuer of the credential.| +|`CredentialType`| ✔️|`string`|`Blob`|A (hex-encoded) value to identify the type of credential from the issuer.| +|`Expiration`| |`number`|`UInt32`|Optional credential expiration.| +|`URI`| |`string`|`Blob`|Optional additional data about the credential (such as a link to the VC document).| +|`OwnerNode`|✔️|`string`|`UInt64`|A hint indicating which page of the sender's owner directory links to this object, in case the directory consists of multiple pages. Note: The object does not contain a direct link to the owner directory containing it, since that value can be derived from the `Account.PreviousTxnID`.| +|`PreviousTxnID`|✔️|`string`|`Hash256`|The identifying hash of the transaction that most recently modified this object.| +|`PreviousTxnLgrSeqNumber`|✔️|`number`|`UInt32`|The index of the ledger that contains the transaction that most recently modified this object.| + +#### 2.1.1. Object ID + +The ID of this object will be a hash that incorporates the `Subject`, `Issuer`, and `CredentialType` fields, combined with a unique space key for `Credential` objects, which will be defined during implementation. + +#### 2.1.2. `Flags` +| Flag Name | Flag Value | +|-----------|------------| +|`lsfAccepted`|`0x00010000`| + +`lsfAccepted` is on if the subject of the credential has accepted the credential. If it is off, the issuer has the reserve burden; if it is on, the burden moves to the subject. + +#### 2.1.3. `CredentialType` + +This value is similar to the NFT `Taxon` value, where the value's meaning will be decided by the issuer. It may be the same as a claim in a VC, but could also represent a subset of such a claim. + +### 2.2. Account Deletion + +The `Credential` object is not a [deletion blocker](https://xrpl.org/docs/concepts/accounts/deleting-accounts/#requirements). + +## 3. On-Ledger Object: `DepositPreauth` + +The `DepositPreauth` object tracks a preauthorization from one account to another. This object already exists on the XRPL, but is being extended as a part of this spec to also support credential preauthorization. + +### 3.1. Fields +
+ + +As a reference, [here](https://xrpl.org/docs/references/protocol/ledger-data/ledger-entry-types/depositpreauth/#depositpreauth-fields) are the existing fields for the `DepositPreauth` object. + + +| Field Name | Required? | JSON Type | Internal Type | Description | +|------------|-----------|-----------|---------------|-------------| +|`Account`|✔️|`string`|`AccountID`|The account that granted the preauthorization (the destination of the preauthorized payments).| +|`Authorize`|✔️|`string`|`AccountID`|The account that received the preauthorization (the sender of the preauthorized payments).| +|`LedgerEntryType`|✔️|`string`|`UInt16`|The value `0x0070`, mapped to the string `"DepositPreauth"`, indicates that this is a `DepositPreauth` object.| +|`OwnerNode`|✔️|`string`|`UInt64`|A hint indicating which page of the sender's owner directory links to this object, in case the directory consists of multiple pages. Note: The object does not contain a direct link to the owner directory containing it, since that value can be derived from the `Account.PreviousTxnID`.| +|`PreviousTxnID`|✔️|`string`|`Hash256`|The identifying hash of the transaction that most recently modified this object.| +|`PreviousTxnLgrSeqNumber`|✔️|`number`|`UInt32`|The index of the ledger that contains the transaction that most recently modified this object.| +
+ +We propose these modifications: + +| Field Name | Required? | JSON Type | Internal Type | Description | +|------------|-----------|-----------|---------------|-------------| +|`Authorize`| |`string`|`AccountID`|The account that received the preauthorization. (The sender of the preauthorized payments.)| +|`AuthorizeCredentials`| |`array`|`STArray`|The credential that received the preauthorization. (Any account with this credential can send preauthorized payments).| + +#### 3.1.1. Object ID + +The ID of this object will be either a hash of the `Account` and `Authorize` fields (as it currently is), or a hash of the `Account` and the contents of `AuthorizeCredentials` fields, combined with the unique space key for `DepositAuth` objects: `0x0070`. + +#### 3.1.2. `Authorize` + +This field is now optional, and a valid `DepositPreauth` object must either have the `Authorize` field or the `AuthorizeCredentials` field. + +#### 3.1.3. `AuthorizeCredentials` + +This field is an array of inner objects. The contents of these inner objects determine the credential(s) that are accepted. + +If more than one credential is included in the list, all of those credentials must be included (effectively ANDing them together). + +The list has a maximum size of 8 credentials. + +| Field Name | Required? | JSON Type | Internal Type | Description | +|------------|-----------|-----------|---------------|-------------| +|`Issuer`|✔️|`string`|`AccountID`|The issuer of the credential.| +|`CredentialType`|✔️|`string`|`Blob`|A (hex-encoded) value to identify the type of credential from the issuer.| + +## 4. Transaction: `DepositPreauth` + +This transaction currently creates and deletes `DepositPreauth` objects, thereby whitelisting and unwhitelisting accounts. + +This spec extends that functionality to also support whitelisting and unwhitelisting credentials. + +### 4.1. Fields + +As a reference, [here](https://xrpl.org/docs/references/protocol/transactions/types/depositpreauth/#depositpreauth-fields) are the existing fields for the `DepositPreauth` transaction: + +| Field Name | Required? | JSON Type | Internal Type | Description | +|------------|-----------|-----------|---------------|-------------| +|`Authorize`| |`string`|`AccountID`|The XRP Ledger address of the sender to preauthorize. | +|`Unauthorize` | |`string`|`AccountID`|The XRP Ledger address of a sender whose preauthorization should be revoked.| + +This proposal adds two new fields: +| Field Name | Required? | JSON Type | Internal Type | Description | +|------------|-----------|-----------|---------------|-------------| +|`AuthorizeCredentials`| |`array`|`STArray`|The credential(s) to preauthorize. | +|`UnauthorizeCredentials` | |`array`|`STArray`|The credential(s) whose preauthorization should be revoked.| + +#### 4.1.1. `AuthorizeCredentials` and `UnauthorizeCredentials` + +These fields follow the same rules outlined in section 3.1.3 for the `Credential` object's `AuthorizeCredentials` field. + +### 4.2. Failure Conditions +* Existing failure conditions for `DepositPreauth` will still be obeyed. +* None or more than one of `Authorize`, `Unauthorize`, `AuthorizeCredentials`, and `UnauthorizeCredentials` are included (i.e. there must be exactly one of these fields included). +* The issuer of the credential doesn't exist. +* If `UnauthorizeCredentials` is included in the transaction, the credential(s) are not currently authorized. +* If `AuthorizeCredentials` is included in the transaction: + * The credential(s) are already authorized. + * The account doesn't have enough reserve for the object. + * The array is too long (i.e. has more than 8 credentials). + * The array is empty (i.e. has no credentials). + +### 4.3. State Changes + +If the transaction is successful: +* The `DepositPreauth` object is created or deleted. + +## 5. Transaction: `CredentialCreate` + +This transaction creates a `Credential` object. + +There are two possible methods of doing so: +* The issuer submits this transaction, and `CredentialAccept` is used for the subject to accept the transaction. +* The credential data is passed off-chain from the issuer to the subject. The subject then submits the credential themselves, alongside an issuer signature, to the ledger. + +### 5.1. Fields + +| Field Name | Required? | JSON Type | Internal Type | Description | +|------------|-----------|-----------|---------------|-------------| +|`TransactionType`| ✔️|`string`|`UInt16`|The transaction type (`CredentialCreate`).| +|`Account`| ✔️|`string`|`AccountID`|The subject or issuer of the credential.| +|`Subject`| |`string`|`AccountID`|The subject of the credential.| +|`Issuer`| |`string`|`AccountID`|The issuer of the credential.| +|`CredentialType`|✔️|`string`|`Blob`|A (hex-encoded) value to identify the type of credential from the issuer.| +|`Signature`| |`string`|`Blob`|A signature from the issuer attesting to the credential.| +|`Expiration`| |`number`|`UInt32`|Optional credential expiration.| +|`URI`| |`string`|`Blob`|Optional additional data about the credential (such as a link to the VC document).| + +#### 5.1.1. `Subject` and `Issuer` + +Only one of these two fields must be specified. If `Subject` is specified, `Account` is the issuer. If `Issuer` is specified, `Account` is the subject. + +#### 5.1.2. `Signature` + +If the subject is submitting the account, a signature must be included from the issuer attesting to the credential. This signature will sign a simple JSON that looks something like this: +```typescript +{ + Issuer: "rISABEL......", + Subject: "rALICE.......", + CredentialType: "123ABC", +} +``` + +### 5.2. Failure Conditions + +* Both or neither `Subject` and `Issuer` are specified (i.e. there must be only one of the two fields). +* The account in `Subject`/`Issuer` doesn't exist. +* `Issuer` is included but `Signature` is not. +* The time in `Expiration` is in the past. +* The `URI` field is too long (limit 256 bytes). +* The account doesn't have enough reserve for the object. + +### 5.3. State Changes + +If the transaction is successful: +* The `Credential` object is created. +* If `Issuer` == `Account`, then the `lsfAccepted` flag is enabled. + +## 6. Transaction: `CredentialAccept` + +This transaction transfers a credential from the `Issuer` to the `Account`. It is not a valid credential until it has been transferred. + +### 6.1. Fields + +| Field Name | Required? | JSON Type | Internal Type | Description | +|------------|-----------|-----------|---------------|-------------| +|`TransactionType`| ✔️|`string`|`UInt16`|The transaction type (`CredentialAccept`).| +|`Account`| ✔️|`string`|`AccountID`|The subject of the credential.| +|`Issuer`| ✔️|`string`|`AccountID`|The issuer of the credential.| +|`CredentialType`|✔️|`string`|`Blob`|A (hex-encoded) value to identify the type of credential from the issuer.| + +### 6.2. Failure Conditions + +* The account in `Account` or `Issuer` doesn't exist. +* There is no valid credential described by the fields of the transaction. +* The credential has already been accepted. +* The `Account` doesn't have enough reserve for the object. + +### 6.3. State Changes + +If the transaction is successful: +* The `lsfAccepted` flag is turned on in the credential. +* The `Credential` object is moved from the issuer's owner directory to the subject's. + +## 7. Transaction: `CredentialDelete` + +This transaction deletes a `Credential` object. + +It can be executed by: +* The issuer, anytime. +* The account, anytime. +* Anyone, after the expiration time is up. + +### 7.1. Fields + +| Field Name | Required? | JSON Type | Internal Type | Description | +|------------|-----------|-----------|---------------|-------------| +|`TransactionType`| ✔️|`string`|`UInt16`|The transaction type (`CredentialDelete`).| +|`Account`| ✔️|`string`|`AccountID`|The transaction submitter.| +|`Subject`| |`string`|`AccountID`|The person that the credential is for. If omitted, `Account` is assumed to be the subject.| +|`Issuer`| |`string`|`AccountID`|The issuer of the credential. If omitted, `Account` is assumed to be the issuer.| +|`CredentialType`|✔️|`string`|`Blob`|A (hex-encoded) value to identify the type of credential from the issuer.| + +### 7.2. Failure Conditions + +* The credential described by the `Subject`, `Issuer`, and `CredentialType` fields doesn't exist. +* The `Account` isn't the issuer or account, and the expiration hasn't passed. + +### 7.3. State Changes + +If the transaction is successful: +* The `Credential` object is deleted. + +## 8. Transactions: Common Fields + +### 8.1. Fields + +As a reference, [here](https://xrpl.org/docs/references/protocol/transactions/common-fields/) are the fields that all transactions currently have. + + + +| Field Name | Required? | JSON Type | Internal Type | +|------------|-----------|-----------|---------------| +|`CredentialIDs`| ✔️|`array`|`Vector256`|Credential(s) to attach to the transaction.| + +Transactions that accept this field: +* Basically anything with a `Destination` field (like a payment) or something that has to be accepted by the destination (like an escrow/check). + +### 8.2. Failure Conditions + +* Any of the `CredentialIDs` isn't an object that exists. +* Any of the `CredentialIDs` isn't a `Credential` object. +* Any of the `CredentialIDs` is an expired `Credential` object. +* `CredentialIDs` is included, but the destination doesn't have Deposit Authorization set up, or the transaction doesn't have a destination (e.g. `AccountSet`). +* The `CredentialIDs` are not authorized by the destination. + +Note: the transaction will still fail if too many credentials are included. The exact list must be provided. + +### 8.3. State Changes + +* If the credential isn't valid, it gets blocked. +* If the credential is expired, it is deleted. + +## 9. RPC: `deposit_authorized` + +The [`deposit_authorized` RPC method](https://xrpl.org/deposit_authorized.html) already exists on the XRPL. This proposal suggests some modifications to also support permissioned DEX domains. + +### 9.1. Request Fields + +| Field Name | Required? | JSON Type | Description | +|------------|-----------|-----------|-------------| +|`source_account`|✔️|`string`|The sender of a possible payment.| +|`destination_account`|✔️|`string`|The recipient of a possible payment.| +|`ledger_hash`| |`string`|A 20-byte hex string for the ledger version to use. | +|`ledger_index`| |`string` or `number`|The ledger index of the ledger to use, or a shortcut string to choose a ledger automatically.| + +This proposal puts forward the following addition: + +| Field Name | Required? | JSON Type | Description | +|------------|-----------|-----------|-------------| +|`credentials`| |`array`|The object IDs of `Credential` objects. If this field is included, then the credential will be taken into account when analyzing whether the sender can send funds to the destination.| + +### 9.2. Response Fields + +| Field Name | Always Present? | JSON Type | Description | +|------------|-----------------|-----------|-------------| +|`deposit_authorized`|✔️|`boolean`|Whether the specified source account is authorized to send payments directly to the destination account. If true, either the destination account does not require deposit authorization or the source account is preauthorized.| +|`destination_account`|✔️|`string`|The destination account specified in the request.| +|`source_account`|✔️|`string`|The source account specified in the request.| +|`ledger_hash`| |`string`|The identifying hash of the ledger that was used to generate this response.| +|`ledger_index`| |`number`|The ledger index of the ledger version that was used to generate this response.| +|`ledger_current_index`| |`number`|The ledger index of the current in-progress ledger version, which was used to generate this response.| +|`validated`| |`boolean`|If true, the information comes from a validated ledger version.| + +## 10. Compliance with W3C Spec + +This proposal prioritizes interoperability with the [W3C Verifiable Credential (VC) spec](https://www.w3.org/TR/vc-data-model/). The existing verification flow for XRPL-based Verifiable Credentials remains the primary method: +1. **DID Resolution:** Verifiers access the DID document from the DID ID (e.g., `did:xrpl:r....`). This document is stored in the account's [DID object](https://xrpl.org/docs/references/protocol/ledger-data/ledger-entry-types/did). +2. **VC Access:** The DID document provides a link to the relevant Verifiable Credentials. +3. **VC Verification:** Based on access permissions, verifiers can then view and verify the retrieved VCs. + +However, this proposal introduces an optional enhancement. Within the `Credential` object, the `URI` field can also point to the VC. It's important to note that this pointer is entirely optional, and the core verification process using DID resolution will still be the primary method for XRPL credential verification. + +It is recommended that anyone who holds a credential also have a DID object, to increase compliance with the W3C VC spec. + +Note that the issuer of the on-chain `Credential` does not have to be the same as the issuer of the VC, and the on-chain object can instead essentially serve as an on-chain attestation from the issuer for the VC. + +## 11. Invariants + +### 11.1. Reserves + +The burden of reserve should be with the issuer, and the credential should be in the issuer's owner directory, if the `lsfAccepted` flag is off. The burden of reserve should be with the subject and the credential should be in the subject's owner directory, if the `lsfAccepted` flag is on. + +### 11.2. The `DepositPreauth` Object + +A `DepositPreauth` ledger object always has exactly one of the `Authorize` field and the `AuthorizeCredentials` field. + +If the `AuthorizeCredentials` field is included, the array contains between 1 and 8 credentials. + +## 12. Examples + +In this example, a trusted issuer, Isabel, is issuing a credential that indicates that Alice is KYC'd. Verity is setting up her account to only interact with accounts that Isabel has attested to being properly KYC'd. + +For ease of reading, some of the common transaction fields, such as signatures and public keys, have been left out of this example. + +### 12.1. `CredentialCreate` + +Isabel creates the credential for Alice, after confirming her KYC status off-chain. + +```typescript +{ + TransactionType: "CredentialCreate", + Account: "rISABEL......", + Subject: "rALICE.......", + CredentialType: "4B5943", // "KYC" in hex + Expiration: 789004799, // the end of the year + URI: "isabel.com/credentials/kyc/alice" // This will be converted into hex +} +``` + +### 12.2. The `Credential` Object + +This is the object created by the `CredentialCreate` transaction. + +```typescript +{ + LedgerEntryType: "Credential", + Flags: 0, + Subject: "rALICE.......", + Issuer: "rISABEL......", + CredentialType: "123ABC", + Expiration: 789004799, // the end of the year + URI: "isabel.com/credentials/kyc/alice" // This will be converted into hex +} +``` + +### 12.3. `CredentialAccept` + +Alice accepts the credential, thereby making it valid. + +```typescript +{ + TransactionType: "CredentialAccept", + Account: "rALICE.......", + Issuer: "rISABEL......", + CredentialType: "123ABC" +} +``` + +### 12.4. `DepositPreauth` + +Verity sets up her account to only interact with accounts that Isabel has KYC'd. + +```typescript +{ + TransactionType: "DepositPreauth", + Account: "rVERITY......", + AuthorizeCredentials: [ + { + Credential: { + Issuer: "rISABEL......", + CredentialType: "4B5943" + } + } + ] +} +``` + +### 12.5. Payments + +This transaction will succeed, since Alice has attached the authorized credential from Isabel. + +```typescript +{ + TransactionType: "Payment", + Account: "rALICE......", + Destination: "rVERITY......", + Amount: "10000000", + CredentialIDs: ["DD40031C6C21164E7673...17D467CEEE9"] +} +``` + +This transaction will fail, since Alice has not attached the authorized credential from Isabel. This is akin to trying to go through airport security without a form of ID. + +```typescript +{ + TransactionType: "Payment", + Account: "rALICE......", + Destination: "rVERITY......", + Amount: "10000000" +} +``` + +This transaction will fail, since the attached credential isn't Bob's. + +```typescript +{ + TransactionType: "Payment", + Account: "rBOB......", + Destination: "rVERITY......", + Amount: "10000000", + CredentialIDs: ["DD40031C6C21164E7673...17D467CEEE9"] +} +``` + +This transaction will fail, since Bob doesn't have a valid credential from Isabel. + +```typescript +{ + TransactionType: "Payment", + Account: "rBOB......", + Destination: "rVERITY......", + Amount: "10000000" +} +``` + +This transaction will fail, since Bob doesn't have Deposit Authorization set up. + +```typescript +{ + TransactionType: "Payment", + Account: "rALICE......", + Destination: "rBOB......", + Amount: "10000000", + CredentialIDs: ["DD40031C6C21164E7673...17D467CEEE9"] +} +``` + +## 13. Security + +### 13.1. Trust Assumptions + +You need to trust the issuer to only be issuing valid credentials, and to not delete a credential without a legitimate reason. + +### 13.2. Data Privacy + +No private data needs to be stored on-chain (e.g. all the KYC data). The actual VC can still be stored off-chain. It could be stored at a link in the `URI` field. + +# Appendix + +## Appendix A: FAQ + +### A.1: Do I have to only use credentials with the Deposit Authorization feature? Can I also use them for off-chain purposes? + +You can use credentials for any purpose you'd like, not just for Deposit Authorization. + +### A.2: Do I need to use credentials for VCs or can I use them for other things? + +You can use credentials for any purpose you'd like. The recommended usecase is VCs, but there are plenty of other usecases for them. + +### A.3: Why not use NFTs instead, with a certain issuer-taxon combo and the `tfTransferable` flag unset? + +Using NFTs instead wouldn't be as elegant, since it means that the NFT has to follow a specific format. It would make more sense for an off-ledger use-case, not directly on-ledger. In addition, an NFT serves different needs - e.g. NFTs don't have an expiration. + +### A.4: Can an issuer issue a credential for themselves? + +Yes. + +### A.5: Can an issuer edit the details of a credential once it's created? + +No, it would have to be deleted and recreated. This is similar to needing to get a new card if your license/passport expires. If the `Subject`, `Issuer`, and `CredentialType` stay the same, though, the object will still have the same ID as before. + +### A.6: Why do I need to include the `CredentialIDs` field in my transaction? Shouldn't the XRPL be able to figure out whether I have a valid credential automatically? + +There is no way for the XRPL to iterate through just the list of credentials an account has; it can only iterate through the entire list of account objects. This is an unbounded list of objects (it could be millions of objects). Even just the list of accepted credentials could theoretically be millions of objects long. It could cause serious performance issues if the system had to iterate through the whole list. + +It's much faster to have the credential ID included - it's easy to make sure that that's a valid credential, and check that it's an authorized credential. + +### A.7: Can a credential issuer delete their account? + +Yes, even if they still have issued credentials in existence. + +### A.8: Does a credential issue have to have an on-chain account? + +No, though they must have a valid keypair. If the second method of creating a credential is used (via a signature from the issuer), the issuer can still attest to a credential without having to have an account on-chain. This is to ensure closer compliance with the W3C Verifiable Credentials spec (see section 9). + +### A.9: How do I get a list of credentials that an issuer has issued? + +The answer to that question is still being investigated. One option would be a Clio API. + +### A.10: Can I edit the list of credentials stored in `AuthorizeCredentials`? + +No, you have to delete the `DepositPreauth` object and recreate it with the new list. + +### A.11: Does the list of credentials in `AuthorizeCredentials` _have_ to be AND-ed together? Can I instead use it as an OR list (i.e. only provide one of the credentials instead of all)? Or some complex combination? + +No. You can OR credential(s) by putting them in separate `DepositPreauth` objects. For performance reasons, it is much easier to do a credential lookup if you need to have all of the credentials. Otherwise, you'd have to search the whole list. In addition, people who need to use this feature will likely not find the object reserve cost-prohibitive. + +### A.12: Why are `CredentialCreate` and `CredentialDelete` separate transactions? + +It's easier and clearer to have those be separate operations. From f850957206d8983b3ff441a36effe84efb4823ad Mon Sep 17 00:00:00 2001 From: Mayukha Vadari Date: Fri, 2 Aug 2024 16:03:02 -0400 Subject: [PATCH 04/26] XLS-0070d-credentials/README.md updated from https://stackedit.io/ From f2db5d9c10e46a9529bbab92bd08b5ec18d7b999 Mon Sep 17 00:00:00 2001 From: Mayukha Vadari Date: Fri, 2 Aug 2024 16:03:47 -0400 Subject: [PATCH 05/26] fix typo --- XLS-0070d-simulate/README.md | 573 ----------------------------------- 1 file changed, 573 deletions(-) delete mode 100644 XLS-0070d-simulate/README.md diff --git a/XLS-0070d-simulate/README.md b/XLS-0070d-simulate/README.md deleted file mode 100644 index 8cb0ee1d..00000000 --- a/XLS-0070d-simulate/README.md +++ /dev/null @@ -1,573 +0,0 @@ -
-Title:       On-Chain Credentials
-Revision:    3
-
-Author:      Mayukha Vadari
-
-Affiliation: Ripple
-
- -# On-Chain Credentials - -## Abstract - -The XRPL DID (Digital Identifier) amendment ([XLS-40](https://github.com/XRPLF/XRPL-Standards/tree/master/XLS-0040d-decentralized-identity)) empowers users to manage their digital identities on the XRP Ledger. While this amendment adds support for on-chain identity management and simplifies off-chain credential usage, maximizing blockchain technology's full potential for credential handling requires on-chain solutions. - -This document proposes a design to bridge this gap. It outlines the issuance, storage, and verification of credentials directly on the XRP Ledger, while still supporting the privacy needs of users. - -On-chain credentialing can streamline various processes within the XRPL ecosystem. For example, financial institutions can issue credentials on the XRP Ledger, attesting to a user's identity and compliance. This eliminates the need for repeated [KYC (Know Your Customer)](https://en.wikipedia.org/wiki/Know_your_customer) checks across different platforms, fostering a smoother user experience. By enabling secure credential management, this proposal unlocks the potential for a new wave of trust-based applications within the XRPL ecosystem. - -## 1. Overview - -This design adds support for creating, accepting, and deleting credentials. It also extends the existing [Deposit Authorization](https://xrpl.org/docs/concepts/accounts/depositauth) feature, allowing accounts to not only whitelist specific accounts, but also whitelist accounts with specific credentials. - -This proposal only supports blocking the interactions that Deposit Authorization supports, such as direct payments. However, future proposals could add support for credential-gating in other parts of the XRPL, such as AMMs or lending pools. - -We propose: -* Creating a `Credential` ledger object -* Modifying the `DepositPreauth` ledger object -* Modifying the `DepositPreauth` transaction -* Creating a `Credential` ledger object -* Creating a `CredentialCreate` transaction type -* Creating a `CredentialAccept` transaction type -* Creating a `CredentialDelete` transaction type - -This feature will require an amendment, tentatively titled `featureCredentialAuth`. - -### 1.1. Background: DIDs and Verifiable Credentials (VCs) - -A [verifiable credential](https://en.wikipedia.org/wiki/Verifiable_credentials) (VC), as defined by the [W3C specification](https://www.w3.org/TR/vc-data-model-2.0/), is a secure and tamper-evident way to represent information about a subject, such as an individual, organization, or even an IoT device. These credentials are issued by a trusted entity and can be verified by third parties without directly involving the issuer at all. - -For a clearer understanding of the relationship between [DIDs (Decentralized Identifiers)](https://en.wikipedia.org/wiki/Decentralized_identifier) and VCs, a real-world example is considered. A DID serves as a unique identifier for an entity, similar to a fingerprint or a photo of a person (their physical characteristics). In contrast, a VC acts as a verifiable piece of information associated with that DID, much like a driver's license or passport. When a third party needs to verify an identity claim, they can examine the VC presented by the entity and ensure it aligns with the corresponding DID (such as comparing the photo on a driver's license to the physical characteristics of the person to whom it supposedly belongs). - -### 1.2. Terminology - -* **Credential**: A representation of one or more assertions made by an issuer. For example, a passport is a representation of the assertion that a person is a citizen of a given country. -* **Issuer**: The account that creates (issues) the credential. For example, a passport is issued by a country's government. -* **Subject**: The account that the credential is issued to. For example, a passport is issued to a specific person. -* **Whitelist**: A list of accounts that are allowed to do a given action, or (if used as a verb) the action of adding an account to said list. -* **Preauthorization**: Essentially the same thing as whitelisting. - -*Note: These definitions do not directly match the definitions listed in the [W3C Verifiable Credentials spec](https://www.w3.org/TR/vc-data-model-2.0/#terminology). These terms are used in a slightly different way in the context of this spec.* - -### 1.3. Basic Flow - -In this scenario, an authorizer/verifier account, Verity, is a regulated entity wants to ensure that she is only interacting with properly KYC'd accounts. - -* Verity sets up her account such that she only wants to interact with properly KYC'd accounts. He trusts Isabel, a credential issuer, to properly vet accounts and issue credentials attesting to that. -* Alice, who wants to interact with Verity's account, submits her KYC documents to Isabel off-chain. Isabel creates a credential attesting to her trustworthiness on-chain. -* Alice accepts the credential, making it a valid credential. -* Alice can now interact with/send funds to Verity. - -## 2. On-Ledger Object: `Credential` - -This object will be an on-chain representation of a credential, while ensuring that any sensitive details are kept off-chain, to protect the subject's privacy. - -### 2.1. Fields - -| Field Name | Required? | JSON Type | Internal Type | Description | -|------------|-----------|-----------|---------------|-------------| -|`LedgerEntryType`| ✔️|`string`|`UInt16`|The ledger object's type (`Credential`).| -|`Flags`| ✔️|`number`|`UInt32`|Flag values associated with this object.| -|`Subject`| ✔️|`string`|`AccountID`|The account that the credential is for.| -|`Issuer`| ✔️|`string`|`AccountID`|The issuer of the credential.| -|`CredentialType`| ✔️|`string`|`Blob`|A (hex-encoded) value to identify the type of credential from the issuer.| -|`Expiration`| |`number`|`UInt32`|Optional credential expiration.| -|`URI`| |`string`|`Blob`|Optional additional data about the credential (such as a link to the VC document).| -|`OwnerNode`|✔️|`string`|`UInt64`|A hint indicating which page of the sender's owner directory links to this object, in case the directory consists of multiple pages. Note: The object does not contain a direct link to the owner directory containing it, since that value can be derived from the `Account.PreviousTxnID`.| -|`PreviousTxnID`|✔️|`string`|`Hash256`|The identifying hash of the transaction that most recently modified this object.| -|`PreviousTxnLgrSeqNumber`|✔️|`number`|`UInt32`|The index of the ledger that contains the transaction that most recently modified this object.| - -#### 2.1.1. Object ID - -The ID of this object will be a hash that incorporates the `Subject`, `Issuer`, and `CredentialType` fields, combined with a unique space key for `Credential` objects, which will be defined during implementation. - -#### 2.1.2. `Flags` -| Flag Name | Flag Value | -|-----------|------------| -|`lsfAccepted`|`0x00010000`| - -`lsfAccepted` is on if the subject of the credential has accepted the credential. If it is off, the issuer has the reserve burden; if it is on, the burden moves to the subject. - -#### 2.1.3. `CredentialType` - -This value is similar to the NFT `Taxon` value, where the value's meaning will be decided by the issuer. It may be the same as a claim in a VC, but could also represent a subset of such a claim. - -### 2.2. Account Deletion - -The `Credential` object is not a [deletion blocker](https://xrpl.org/docs/concepts/accounts/deleting-accounts/#requirements). - -## 3. On-Ledger Object: `DepositPreauth` - -The `DepositPreauth` object tracks a preauthorization from one account to another. This object already exists on the XRPL, but is being extended as a part of this spec to also support credential preauthorization. - -### 3.1. Fields -
- - -As a reference, [here](https://xrpl.org/docs/references/protocol/ledger-data/ledger-entry-types/depositpreauth/#depositpreauth-fields) are the existing fields for the `DepositPreauth` object. - - -| Field Name | Required? | JSON Type | Internal Type | Description | -|------------|-----------|-----------|---------------|-------------| -|`Account`|✔️|`string`|`AccountID`|The account that granted the preauthorization (the destination of the preauthorized payments).| -|`Authorize`|✔️|`string`|`AccountID`|The account that received the preauthorization (the sender of the preauthorized payments).| -|`LedgerEntryType`|✔️|`string`|`UInt16`|The value `0x0070`, mapped to the string `"DepositPreauth"`, indicates that this is a `DepositPreauth` object.| -|`OwnerNode`|✔️|`string`|`UInt64`|A hint indicating which page of the sender's owner directory links to this object, in case the directory consists of multiple pages. Note: The object does not contain a direct link to the owner directory containing it, since that value can be derived from the `Account.PreviousTxnID`.| -|`PreviousTxnID`|✔️|`string`|`Hash256`|The identifying hash of the transaction that most recently modified this object.| -|`PreviousTxnLgrSeqNumber`|✔️|`number`|`UInt32`|The index of the ledger that contains the transaction that most recently modified this object.| -
- -We propose these modifications: - -| Field Name | Required? | JSON Type | Internal Type | Description | -|------------|-----------|-----------|---------------|-------------| -|`Authorize`| |`string`|`AccountID`|The account that received the preauthorization. (The sender of the preauthorized payments.)| -|`AuthorizeCredentials`| |`array`|`STArray`|The credential that received the preauthorization. (Any account with this credential can send preauthorized payments).| - -#### 3.1.1. Object ID - -The ID of this object will be either a hash of the `Account` and `Authorize` fields (as it currently is), or a hash of the `Account` and the contents of `AuthorizeCredentials` fields, combined with the unique space key for `DepositAuth` objects: `0x0070`. - -#### 3.1.2. `Authorize` - -This field is now optional, and a valid `DepositPreauth` object must either have the `Authorize` field or the `AuthorizeCredentials` field. - -#### 3.1.3. `AuthorizeCredentials` - -This field is an array of inner objects. The contents of these inner objects determine the credential(s) that are accepted. - -If more than one credential is included in the list, all of those credentials must be included (effectively ANDing them together). - -The list has a maximum size of 8 credentials. - -| Field Name | Required? | JSON Type | Internal Type | Description | -|------------|-----------|-----------|---------------|-------------| -|`Issuer`|✔️|`string`|`AccountID`|The issuer of the credential.| -|`CredentialType`|✔️|`string`|`Blob`|A (hex-encoded) value to identify the type of credential from the issuer.| - -## 4. Transaction: `DepositPreauth` - -This transaction currently creates and deletes `DepositPreauth` objects, thereby whitelisting and unwhitelisting accounts. - -This spec extends that functionality to also support whitelisting and unwhitelisting credentials. - -### 4.1. Fields - -As a reference, [here](https://xrpl.org/docs/references/protocol/transactions/types/depositpreauth/#depositpreauth-fields) are the existing fields for the `DepositPreauth` transaction: - -| Field Name | Required? | JSON Type | Internal Type | Description | -|------------|-----------|-----------|---------------|-------------| -|`Authorize`| |`string`|`AccountID`|The XRP Ledger address of the sender to preauthorize. | -|`Unauthorize` | |`string`|`AccountID`|The XRP Ledger address of a sender whose preauthorization should be revoked.| - -This proposal adds two new fields: -| Field Name | Required? | JSON Type | Internal Type | Description | -|------------|-----------|-----------|---------------|-------------| -|`AuthorizeCredentials`| |`array`|`STArray`|The credential(s) to preauthorize. | -|`UnauthorizeCredentials` | |`array`|`STArray`|The credential(s) whose preauthorization should be revoked.| - -#### 4.1.1. `AuthorizeCredentials` and `UnauthorizeCredentials` - -These fields follow the same rules outlined in section 3.1.3 for the `Credential` object's `AuthorizeCredentials` field. - -### 4.2. Failure Conditions -* Existing failure conditions for `DepositPreauth` will still be obeyed. -* None or more than one of `Authorize`, `Unauthorize`, `AuthorizeCredentials`, and `UnauthorizeCredentials` are included (i.e. there must be exactly one of these fields included). -* The issuer of the credential doesn't exist. -* If `UnauthorizeCredentials` is included in the transaction, the credential(s) are not currently authorized. -* If `AuthorizeCredentials` is included in the transaction: - * The credential(s) are already authorized. - * The account doesn't have enough reserve for the object. - * The array is too long (i.e. has more than 8 credentials). - * The array is empty (i.e. has no credentials). - -### 4.3. State Changes - -If the transaction is successful: -* The `DepositPreauth` object is created or deleted. - -## 5. Transaction: `CredentialCreate` - -This transaction creates a `Credential` object. - -There are two possible methods of doing so: -* The issuer submits this transaction, and `CredentialAccept` is used for the subject to accept the transaction. -* The credential data is passed off-chain from the issuer to the subject. The subject then submits the credential themselves, alongside an issuer signature, to the ledger. - -### 5.1. Fields - -| Field Name | Required? | JSON Type | Internal Type | Description | -|------------|-----------|-----------|---------------|-------------| -|`TransactionType`| ✔️|`string`|`UInt16`|The transaction type (`CredentialCreate`).| -|`Account`| ✔️|`string`|`AccountID`|The subject or issuer of the credential.| -|`Subject`| |`string`|`AccountID`|The subject of the credential.| -|`Issuer`| |`string`|`AccountID`|The issuer of the credential.| -|`CredentialType`|✔️|`string`|`Blob`|A (hex-encoded) value to identify the type of credential from the issuer.| -|`Signature`| |`string`|`Blob`|A signature from the issuer attesting to the credential.| -|`Expiration`| |`number`|`UInt32`|Optional credential expiration.| -|`URI`| |`string`|`Blob`|Optional additional data about the credential (such as a link to the VC document).| - -#### 5.1.1. `Subject` and `Issuer` - -Only one of these two fields must be specified. If `Subject` is specified, `Account` is the issuer. If `Issuer` is specified, `Account` is the subject. - -#### 5.1.2. `Signature` - -If the subject is submitting the account, a signature must be included from the issuer attesting to the credential. This signature will sign a simple JSON that looks something like this: -```typescript -{ - Issuer: "rISABEL......", - Subject: "rALICE.......", - CredentialType: "123ABC", -} -``` - -### 5.2. Failure Conditions - -* Both or neither `Subject` and `Issuer` are specified (i.e. there must be only one of the two fields). -* The account in `Subject`/`Issuer` doesn't exist. -* `Issuer` is included but `Signature` is not. -* The time in `Expiration` is in the past. -* The `URI` field is too long (limit 256 bytes). -* The account doesn't have enough reserve for the object. - -### 5.3. State Changes - -If the transaction is successful: -* The `Credential` object is created. -* If `Issuer` == `Account`, then the `lsfAccepted` flag is enabled. - -## 6. Transaction: `CredentialAccept` - -This transaction transfers a credential from the `Issuer` to the `Account`. It is not a valid credential until it has been transferred. - -### 6.1. Fields - -| Field Name | Required? | JSON Type | Internal Type | Description | -|------------|-----------|-----------|---------------|-------------| -|`TransactionType`| ✔️|`string`|`UInt16`|The transaction type (`CredentialAccept`).| -|`Account`| ✔️|`string`|`AccountID`|The subject of the credential.| -|`Issuer`| ✔️|`string`|`AccountID`|The issuer of the credential.| -|`CredentialType`|✔️|`string`|`Blob`|A (hex-encoded) value to identify the type of credential from the issuer.| - -### 6.2. Failure Conditions - -* The account in `Account` or `Issuer` doesn't exist. -* There is no valid credential described by the fields of the transaction. -* The credential has already been accepted. -* The `Account` doesn't have enough reserve for the object. - -### 6.3. State Changes - -If the transaction is successful: -* The `lsfAccepted` flag is turned on in the credential. -* The `Credential` object is moved from the issuer's owner directory to the subject's. - -## 7. Transaction: `CredentialDelete` - -This transaction deletes a `Credential` object. - -It can be executed by: -* The issuer, anytime. -* The account, anytime. -* Anyone, after the expiration time is up. - -### 7.1. Fields - -| Field Name | Required? | JSON Type | Internal Type | Description | -|------------|-----------|-----------|---------------|-------------| -|`TransactionType`| ✔️|`string`|`UInt16`|The transaction type (`CredentialDelete`).| -|`Account`| ✔️|`string`|`AccountID`|The transaction submitter.| -|`Subject`| |`string`|`AccountID`|The person that the credential is for. If omitted, `Account` is assumed to be the subject.| -|`Issuer`| |`string`|`AccountID`|The issuer of the credential. If omitted, `Account` is assumed to be the issuer.| -|`CredentialType`|✔️|`string`|`Blob`|A (hex-encoded) value to identify the type of credential from the issuer.| - -### 7.2. Failure Conditions - -* The credential described by the `Subject`, `Issuer`, and `CredentialType` fields doesn't exist. -* The `Account` isn't the issuer or account, and the expiration hasn't passed. - -### 7.3. State Changes - -If the transaction is successful: -* The `Credential` object is deleted. - -## 8. Transactions: Common Fields - -### 8.1. Fields - -As a reference, [here](https://xrpl.org/docs/references/protocol/transactions/common-fields/) are the fields that all transactions currently have. - - - -| Field Name | Required? | JSON Type | Internal Type | -|------------|-----------|-----------|---------------| -|`CredentialIDs`| ✔️|`array`|`Vector256`|Credential(s) to attach to the transaction.| - -Transactions that accept this field: -* Basically anything with a `Destination` field (like a payment) or something that has to be accepted by the destination (like an escrow/check). - -### 8.2. Failure Conditions - -* Any of the `CredentialIDs` isn't an object that exists. -* Any of the `CredentialIDs` isn't a `Credential` object. -* Any of the `CredentialIDs` is an expired `Credential` object. -* `CredentialIDs` is included, but the destination doesn't have Deposit Authorization set up, or the transaction doesn't have a destination (e.g. `AccountSet`). -* The `CredentialIDs` are not authorized by the destination. - -Note: the transaction will still fail if too many credentials are included. The exact list must be provided. - -### 8.3. State Changes - -* If the credential isn't valid, it gets blocked. -* If the credential is expired, it is deleted. - -## 9. RPC: `deposit_authorized` - -The [`deposit_authorized` RPC method](https://xrpl.org/deposit_authorized.html) already exists on the XRPL. This proposal suggests some modifications to also support permissioned DEX domains. - -### 9.1. Request Fields - -| Field Name | Required? | JSON Type | Description | -|------------|-----------|-----------|-------------| -|`source_account`|✔️|`string`|The sender of a possible payment.| -|`destination_account`|✔️|`string`|The recipient of a possible payment.| -|`ledger_hash`| |`string`|A 20-byte hex string for the ledger version to use. | -|`ledger_index`| |`string` or `number`|The ledger index of the ledger to use, or a shortcut string to choose a ledger automatically.| - -This proposal puts forward the following addition: - -| Field Name | Required? | JSON Type | Description | -|------------|-----------|-----------|-------------| -|`credentials`| |`array`|The object IDs of `Credential` objects. If this field is included, then the credential will be taken into account when analyzing whether the sender can send funds to the destination.| - -### 9.2. Response Fields - -| Field Name | Always Present? | JSON Type | Description | -|------------|-----------------|-----------|-------------| -|`deposit_authorized`|✔️|`boolean`|Whether the specified source account is authorized to send payments directly to the destination account. If true, either the destination account does not require deposit authorization or the source account is preauthorized.| -|`destination_account`|✔️|`string`|The destination account specified in the request.| -|`source_account`|✔️|`string`|The source account specified in the request.| -|`ledger_hash`| |`string`|The identifying hash of the ledger that was used to generate this response.| -|`ledger_index`| |`number`|The ledger index of the ledger version that was used to generate this response.| -|`ledger_current_index`| |`number`|The ledger index of the current in-progress ledger version, which was used to generate this response.| -|`validated`| |`boolean`|If true, the information comes from a validated ledger version.| - -## 10. Compliance with W3C Spec - -This proposal prioritizes interoperability with the [W3C Verifiable Credential (VC) spec](https://www.w3.org/TR/vc-data-model/). The existing verification flow for XRPL-based Verifiable Credentials remains the primary method: -1. **DID Resolution:** Verifiers access the DID document from the DID ID (e.g., `did:xrpl:r....`). This document is stored in the account's [DID object](https://xrpl.org/docs/references/protocol/ledger-data/ledger-entry-types/did). -2. **VC Access:** The DID document provides a link to the relevant Verifiable Credentials. -3. **VC Verification:** Based on access permissions, verifiers can then view and verify the retrieved VCs. - -However, this proposal introduces an optional enhancement. Within the `Credential` object, the `URI` field can also point to the VC. It's important to note that this pointer is entirely optional, and the core verification process using DID resolution will still be the primary method for XRPL credential verification. - -It is recommended that anyone who holds a credential also have a DID object, to increase compliance with the W3C VC spec. - -Note that the issuer of the on-chain `Credential` does not have to be the same as the issuer of the VC, and the on-chain object can instead essentially serve as an on-chain attestation from the issuer for the VC. - -## 11. Invariants - -### 11.1. Reserves - -The burden of reserve should be with the issuer, and the credential should be in the issuer's owner directory, if the `lsfAccepted` flag is off. The burden of reserve should be with the subject and the credential should be in the subject's owner directory, if the `lsfAccepted` flag is on. - -### 11.2. The `DepositPreauth` Object - -A `DepositPreauth` ledger object always has exactly one of the `Authorize` field and the `AuthorizeCredentials` field. - -If the `AuthorizeCredentials` field is included, the array contains between 1 and 8 credentials. - -## 12. Examples - -In this example, a trusted issuer, Isabel, is issuing a credential that indicates that Alice is KYC'd. Verity is setting up her account to only interact with accounts that Isabel has attested to being properly KYC'd. - -For ease of reading, some of the common transaction fields, such as signatures and public keys, have been left out of this example. - -### 12.1. `CredentialCreate` - -Isabel creates the credential for Alice, after confirming her KYC status off-chain. - -```typescript -{ - TransactionType: "CredentialCreate", - Account: "rISABEL......", - Subject: "rALICE.......", - CredentialType: "4B5943", // "KYC" in hex - Expiration: 789004799, // the end of the year - URI: "isabel.com/credentials/kyc/alice" // This will be converted into hex -} -``` - -### 12.2. The `Credential` Object - -This is the object created by the `CredentialCreate` transaction. - -```typescript -{ - LedgerEntryType: "Credential", - Flags: 0, - Subject: "rALICE.......", - Issuer: "rISABEL......", - CredentialType: "123ABC", - Expiration: 789004799, // the end of the year - URI: "isabel.com/credentials/kyc/alice" // This will be converted into hex -} -``` - -### 12.3. `CredentialAccept` - -Alice accepts the credential, thereby making it valid. - -```typescript -{ - TransactionType: "CredentialAccept", - Account: "rALICE.......", - Issuer: "rISABEL......", - CredentialType: "123ABC" -} -``` - -### 12.4. `DepositPreauth` - -Verity sets up her account to only interact with accounts that Isabel has KYC'd. - -```typescript -{ - TransactionType: "DepositPreauth", - Account: "rVERITY......", - AuthorizeCredentials: [ - { - Credential: { - Issuer: "rISABEL......", - CredentialType: "4B5943" - } - } - ] -} -``` - -### 12.5. Payments - -This transaction will succeed, since Alice has attached the authorized credential from Isabel. - -```typescript -{ - TransactionType: "Payment", - Account: "rALICE......", - Destination: "rVERITY......", - Amount: "10000000", - CredentialIDs: ["DD40031C6C21164E7673...17D467CEEE9"] -} -``` - -This transaction will fail, since Alice has not attached the authorized credential from Isabel. This is akin to trying to go through airport security without a form of ID. - -```typescript -{ - TransactionType: "Payment", - Account: "rALICE......", - Destination: "rVERITY......", - Amount: "10000000" -} -``` - -This transaction will fail, since the attached credential isn't Bob's. - -```typescript -{ - TransactionType: "Payment", - Account: "rBOB......", - Destination: "rVERITY......", - Amount: "10000000", - CredentialIDs: ["DD40031C6C21164E7673...17D467CEEE9"] -} -``` - -This transaction will fail, since Bob doesn't have a valid credential from Isabel. - -```typescript -{ - TransactionType: "Payment", - Account: "rBOB......", - Destination: "rVERITY......", - Amount: "10000000" -} -``` - -This transaction will fail, since Bob doesn't have Deposit Authorization set up. - -```typescript -{ - TransactionType: "Payment", - Account: "rALICE......", - Destination: "rBOB......", - Amount: "10000000", - CredentialIDs: ["DD40031C6C21164E7673...17D467CEEE9"] -} -``` - -## 13. Security - -### 13.1. Trust Assumptions - -You need to trust the issuer to only be issuing valid credentials, and to not delete a credential without a legitimate reason. - -### 13.2. Data Privacy - -No private data needs to be stored on-chain (e.g. all the KYC data). The actual VC can still be stored off-chain. It could be stored at a link in the `URI` field. - -# Appendix - -## Appendix A: FAQ - -### A.1: Do I have to only use credentials with the Deposit Authorization feature? Can I also use them for off-chain purposes? - -You can use credentials for any purpose you'd like, not just for Deposit Authorization. - -### A.2: Do I need to use credentials for VCs or can I use them for other things? - -You can use credentials for any purpose you'd like. The recommended usecase is VCs, but there are plenty of other usecases for them. - -### A.3: Why not use NFTs instead, with a certain issuer-taxon combo and the `tfTransferable` flag unset? - -Using NFTs instead wouldn't be as elegant, since it means that the NFT has to follow a specific format. It would make more sense for an off-ledger use-case, not directly on-ledger. In addition, an NFT serves different needs - e.g. NFTs don't have an expiration. - -### A.4: Can an issuer issue a credential for themselves? - -Yes. - -### A.5: Can an issuer edit the details of a credential once it's created? - -No, it would have to be deleted and recreated. This is similar to needing to get a new card if your license/passport expires. If the `Subject`, `Issuer`, and `CredentialType` stay the same, though, the object will still have the same ID as before. - -### A.6: Why do I need to include the `CredentialIDs` field in my transaction? Shouldn't the XRPL be able to figure out whether I have a valid credential automatically? - -There is no way for the XRPL to iterate through just the list of credentials an account has; it can only iterate through the entire list of account objects. This is an unbounded list of objects (it could be millions of objects). Even just the list of accepted credentials could theoretically be millions of objects long. It could cause serious performance issues if the system had to iterate through the whole list. - -It's much faster to have the credential ID included - it's easy to make sure that that's a valid credential, and check that it's an authorized credential. - -### A.7: Can a credential issuer delete their account? - -Yes, even if they still have issued credentials in existence. - -### A.8: Does a credential issue have to have an on-chain account? - -No, though they must have a valid keypair. If the second method of creating a credential is used (via a signature from the issuer), the issuer can still attest to a credential without having to have an account on-chain. This is to ensure closer compliance with the W3C Verifiable Credentials spec (see section 9). - -### A.9: How do I get a list of credentials that an issuer has issued? - -The answer to that question is still being investigated. One option would be a Clio API. - -### A.10: Can I edit the list of credentials stored in `AuthorizeCredentials`? - -No, you have to delete the `DepositPreauth` object and recreate it with the new list. - -### A.11: Does the list of credentials in `AuthorizeCredentials` _have_ to be AND-ed together? Can I instead use it as an OR list (i.e. only provide one of the credentials instead of all)? Or some complex combination? - -No. You can OR credential(s) by putting them in separate `DepositPreauth` objects. For performance reasons, it is much easier to do a credential lookup if you need to have all of the credentials. Otherwise, you'd have to search the whole list. In addition, people who need to use this feature will likely not find the object reserve cost-prohibitive. - -### A.12: Why are `CredentialCreate` and `CredentialDelete` separate transactions? - -It's easier and clearer to have those be separate operations. From 7f2781b67822f14232e7d419e4cd002dd0743010 Mon Sep 17 00:00:00 2001 From: Mayukha Vadari Date: Tue, 20 Aug 2024 16:02:43 -0400 Subject: [PATCH 06/26] XLS-0070d-credentials/README.md updated from https://stackedit.io/ --- XLS-0070d-credentials/README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/XLS-0070d-credentials/README.md b/XLS-0070d-credentials/README.md index 8cb0ee1d..a182ea0e 100644 --- a/XLS-0070d-credentials/README.md +++ b/XLS-0070d-credentials/README.md @@ -27,7 +27,6 @@ We propose: * Creating a `Credential` ledger object * Modifying the `DepositPreauth` ledger object * Modifying the `DepositPreauth` transaction -* Creating a `Credential` ledger object * Creating a `CredentialCreate` transaction type * Creating a `CredentialAccept` transaction type * Creating a `CredentialDelete` transaction type From f7dc6c86b212788adc0554e892c1acdeb4542cb0 Mon Sep 17 00:00:00 2001 From: Mayukha Vadari Date: Tue, 20 Aug 2024 17:29:59 -0400 Subject: [PATCH 07/26] XLS-0070d-credentials/README.md updated from https://stackedit.io/ --- XLS-0070d-credentials/README.md | 43 +++++++++++++++++++++------------ 1 file changed, 28 insertions(+), 15 deletions(-) diff --git a/XLS-0070d-credentials/README.md b/XLS-0070d-credentials/README.md index a182ea0e..53ada65d 100644 --- a/XLS-0070d-credentials/README.md +++ b/XLS-0070d-credentials/README.md @@ -19,7 +19,7 @@ On-chain credentialing can streamline various processes within the XRPL ecosyste ## 1. Overview -This design adds support for creating, accepting, and deleting credentials. It also extends the existing [Deposit Authorization](https://xrpl.org/docs/concepts/accounts/depositauth) feature, allowing accounts to not only whitelist specific accounts, but also whitelist accounts with specific credentials. +This design adds support for creating, accepting, and deleting credentials. It also extends the existing [Deposit Authorization](https://xrpl.org/docs/concepts/accounts/depositauth) feature, allowing accounts to not only allowlist specific accounts, but also allowlist accounts with specific credentials. This proposal only supports blocking the interactions that Deposit Authorization supports, such as direct payments. However, future proposals could add support for credential-gating in other parts of the XRPL, such as AMMs or lending pools. @@ -31,36 +31,47 @@ We propose: * Creating a `CredentialAccept` transaction type * Creating a `CredentialDelete` transaction type -This feature will require an amendment, tentatively titled `featureCredentialAuth`. +This feature will require an amendment, tentatively titled `CredentialAuth`. ### 1.1. Background: DIDs and Verifiable Credentials (VCs) A [verifiable credential](https://en.wikipedia.org/wiki/Verifiable_credentials) (VC), as defined by the [W3C specification](https://www.w3.org/TR/vc-data-model-2.0/), is a secure and tamper-evident way to represent information about a subject, such as an individual, organization, or even an IoT device. These credentials are issued by a trusted entity and can be verified by third parties without directly involving the issuer at all. -For a clearer understanding of the relationship between [DIDs (Decentralized Identifiers)](https://en.wikipedia.org/wiki/Decentralized_identifier) and VCs, a real-world example is considered. A DID serves as a unique identifier for an entity, similar to a fingerprint or a photo of a person (their physical characteristics). In contrast, a VC acts as a verifiable piece of information associated with that DID, much like a driver's license or passport. When a third party needs to verify an identity claim, they can examine the VC presented by the entity and ensure it aligns with the corresponding DID (such as comparing the photo on a driver's license to the physical characteristics of the person to whom it supposedly belongs). +For a clearer understanding of the relationship between [DIDs (Decentralized Identifiers)](https://en.wikipedia.org/wiki/Decentralized_identifier) and VCs, consider the following analogy. A DID serves as a unique identifier for an entity, similar to a fingerprint or a photo of a person (their physical characteristics). In contrast, a VC acts as a verifiable piece of information associated with that DID, much like a driver's license or passport. When a third party needs to verify an identity claim, they can examine the VC presented by the entity and ensure it aligns with the corresponding DID (such as comparing the photo on a driver's license to the physical characteristics of the person to whom it supposedly belongs). ### 1.2. Terminology * **Credential**: A representation of one or more assertions made by an issuer. For example, a passport is a representation of the assertion that a person is a citizen of a given country. * **Issuer**: The account that creates (issues) the credential. For example, a passport is issued by a country's government. * **Subject**: The account that the credential is issued to. For example, a passport is issued to a specific person. -* **Whitelist**: A list of accounts that are allowed to do a given action, or (if used as a verb) the action of adding an account to said list. -* **Preauthorization**: Essentially the same thing as whitelisting. +* **Allowlist**: A list of accounts that are allowed to do a given action, or (if used as a verb) the action of adding an account to said list. +* **Preauthorization**: Essentially the same thing as allowlisting. *Note: These definitions do not directly match the definitions listed in the [W3C Verifiable Credentials spec](https://www.w3.org/TR/vc-data-model-2.0/#terminology). These terms are used in a slightly different way in the context of this spec.* ### 1.3. Basic Flow -In this scenario, an authorizer/verifier account, Verity, is a regulated entity wants to ensure that she is only interacting with properly KYC'd accounts. +This example scenario features three parties with different roles: + +* Verity is a regulated business that wants to interact only with properly KYC'd accounts, to ensure legal compliance. This makes Verity an _authorizer_ or _verifier_ because they configure which accounts are allowed (authorized) to interact with them. +* Isabel is a credential issuer that vets accounts and issues credentials on-chain attesting that the accounts are who they say they are. +* Alice is a user who wants to interact with Verity. -* Verity sets up her account such that she only wants to interact with properly KYC'd accounts. He trusts Isabel, a credential issuer, to properly vet accounts and issue credentials attesting to that. -* Alice, who wants to interact with Verity's account, submits her KYC documents to Isabel off-chain. Isabel creates a credential attesting to her trustworthiness on-chain. -* Alice accepts the credential, making it a valid credential. -* Alice can now interact with/send funds to Verity. +The authorization flow in this scenario works as follows: + +1. Verity sets up her account so that only authorized accounts can interact with it. Since she trusts Isabel to properly vet accounts and issue credentials attesting to that, she configures her account to accept credentials issued by Isabel. +2. Alice submits her KYC documents to Isabel privately, off-chain. +3. Isabel examines Alice's documents and creates a credential on-chain attesting to Alice's trustworthiness. +4. Alice accepts the credential, making it valid. +5. Alice can now interact with/send funds to Verity. + +Importantly, the KYC documents that Alice sends to Isabel can include personally identifiable or private information that's needed to verify Alice's identity, but this information is never published or stored on-chain and Verity never needs to see it. Also, other businesses that trust Isabel can accept the same credentials so Alice does not need to repeatedly re-verify for every party she wants to interact with. ## 2. On-Ledger Object: `Credential` -This object will be an on-chain representation of a credential, while ensuring that any sensitive details are kept off-chain, to protect the subject's privacy. +This ledger object is an on-chain representation of a credential. + +This object costs one owner reserve for either the issuer or the subject of the credential, depending on whether the subject has accepted it. ### 2.1. Fields @@ -72,8 +83,8 @@ This object will be an on-chain representation of a credential, while ensuring t |`Issuer`| ✔️|`string`|`AccountID`|The issuer of the credential.| |`CredentialType`| ✔️|`string`|`Blob`|A (hex-encoded) value to identify the type of credential from the issuer.| |`Expiration`| |`number`|`UInt32`|Optional credential expiration.| -|`URI`| |`string`|`Blob`|Optional additional data about the credential (such as a link to the VC document).| -|`OwnerNode`|✔️|`string`|`UInt64`|A hint indicating which page of the sender's owner directory links to this object, in case the directory consists of multiple pages. Note: The object does not contain a direct link to the owner directory containing it, since that value can be derived from the `Account.PreviousTxnID`.| +|`URI`| |`string`|`Blob`|Optional additional data about the credential (such as a link to the VC document). This field isn't checked for validity and is limited to a maximum length of 256 bytes.| +|`OwnerNode`|✔️|`string`|`UInt64`|A hint indicating which page of the owner's owner directory links to this object, in case the directory consists of multiple pages. Note: The object does not contain a direct link to the owner directory containing it, since that value can be derived from the `Account.PreviousTxnID`.| |`PreviousTxnID`|✔️|`string`|`Hash256`|The identifying hash of the transaction that most recently modified this object.| |`PreviousTxnLgrSeqNumber`|✔️|`number`|`UInt32`|The index of the ledger that contains the transaction that most recently modified this object.| @@ -92,6 +103,8 @@ The ID of this object will be a hash that incorporates the `Subject`, `Issuer`, This value is similar to the NFT `Taxon` value, where the value's meaning will be decided by the issuer. It may be the same as a claim in a VC, but could also represent a subset of such a claim. +It has a maximum length of 256 bytes. + ### 2.2. Account Deletion The `Credential` object is not a [deletion blocker](https://xrpl.org/docs/concepts/accounts/deleting-accounts/#requirements). @@ -147,9 +160,9 @@ The list has a maximum size of 8 credentials. ## 4. Transaction: `DepositPreauth` -This transaction currently creates and deletes `DepositPreauth` objects, thereby whitelisting and unwhitelisting accounts. +This transaction currently creates and deletes `DepositPreauth` objects, thereby allowlisting and un-allowlisting accounts. -This spec extends that functionality to also support whitelisting and unwhitelisting credentials. +This spec extends that functionality to also support allowlisting and un-allowlisting credentials. ### 4.1. Fields From a5298fd27d75f6abed33c5d29dcc3ec8815f3fe4 Mon Sep 17 00:00:00 2001 From: Mayukha Vadari Date: Thu, 22 Aug 2024 08:06:48 -0400 Subject: [PATCH 08/26] XLS-0070d-credentials/README.md updated from https://stackedit.io/ --- XLS-0070d-credentials/README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/XLS-0070d-credentials/README.md b/XLS-0070d-credentials/README.md index 53ada65d..60fd61b6 100644 --- a/XLS-0070d-credentials/README.md +++ b/XLS-0070d-credentials/README.md @@ -315,7 +315,7 @@ As a reference, [here](https://xrpl.org/docs/references/protocol/transactions/co | Field Name | Required? | JSON Type | Internal Type | |------------|-----------|-----------|---------------| -|`CredentialIDs`| ✔️|`array`|`Vector256`|Credential(s) to attach to the transaction.| +|`CredentialIDs`| |`array`|`Vector256`|Credential(s) to attach to the transaction.| Transactions that accept this field: * Basically anything with a `Destination` field (like a payment) or something that has to be accepted by the destination (like an escrow/check). @@ -325,6 +325,7 @@ Transactions that accept this field: * Any of the `CredentialIDs` isn't an object that exists. * Any of the `CredentialIDs` isn't a `Credential` object. * Any of the `CredentialIDs` is an expired `Credential` object. +* Any of the `CredentialIDs` have not been accepted. * `CredentialIDs` is included, but the destination doesn't have Deposit Authorization set up, or the transaction doesn't have a destination (e.g. `AccountSet`). * The `CredentialIDs` are not authorized by the destination. @@ -332,8 +333,8 @@ Note: the transaction will still fail if too many credentials are included. The ### 8.3. State Changes -* If the credential isn't valid, it gets blocked. -* If the credential is expired, it is deleted. +* If the credential isn't valid, the transaction gets blocked. +* If the credential is expired, the credential is deleted. ## 9. RPC: `deposit_authorized` From cef287df3cdff2bcd34a6484bca11008e5121db2 Mon Sep 17 00:00:00 2001 From: Mayukha Vadari Date: Thu, 22 Aug 2024 09:15:07 -0400 Subject: [PATCH 09/26] XLS-0070d-credentials/README.md updated from https://stackedit.io/ --- XLS-0070d-credentials/README.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/XLS-0070d-credentials/README.md b/XLS-0070d-credentials/README.md index 60fd61b6..eae49173 100644 --- a/XLS-0070d-credentials/README.md +++ b/XLS-0070d-credentials/README.md @@ -322,10 +322,12 @@ Transactions that accept this field: ### 8.2. Failure Conditions -* Any of the `CredentialIDs` isn't an object that exists. -* Any of the `CredentialIDs` isn't a `Credential` object. -* Any of the `CredentialIDs` is an expired `Credential` object. -* Any of the `CredentialIDs` have not been accepted. +* Any of the `CredentialIDs`: + * Isn't an object that exists. + * Isn't a `Credential` object. + * Is an expired `Credential` object. + * Has not been accepted. + * Isn't a credential issued to the `Account` sending the transaction. * `CredentialIDs` is included, but the destination doesn't have Deposit Authorization set up, or the transaction doesn't have a destination (e.g. `AccountSet`). * The `CredentialIDs` are not authorized by the destination. @@ -333,7 +335,7 @@ Note: the transaction will still fail if too many credentials are included. The ### 8.3. State Changes -* If the credential isn't valid, the transaction gets blocked. +* If the credential isn't valid, the transaction fails. * If the credential is expired, the credential is deleted. ## 9. RPC: `deposit_authorized` From 5c1f838905337b2fc92ef75bc60b1a047d831f58 Mon Sep 17 00:00:00 2001 From: Mayukha Vadari Date: Thu, 22 Aug 2024 09:15:11 -0400 Subject: [PATCH 10/26] XLS-0070d-credentials/README.md updated from https://stackedit.io/ --- XLS-0070d-credentials/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/XLS-0070d-credentials/README.md b/XLS-0070d-credentials/README.md index eae49173..72b15d80 100644 --- a/XLS-0070d-credentials/README.md +++ b/XLS-0070d-credentials/README.md @@ -329,7 +329,7 @@ Transactions that accept this field: * Has not been accepted. * Isn't a credential issued to the `Account` sending the transaction. * `CredentialIDs` is included, but the destination doesn't have Deposit Authorization set up, or the transaction doesn't have a destination (e.g. `AccountSet`). -* The `CredentialIDs` are not authorized by the destination. +* The group of `CredentialIDs` are not authorized by the destination. Note: the transaction will still fail if too many credentials are included. The exact list must be provided. From 4b9e226be61462ad14b14f2b13b8e135fe93ac9e Mon Sep 17 00:00:00 2001 From: Mayukha Vadari Date: Thu, 22 Aug 2024 09:15:15 -0400 Subject: [PATCH 11/26] XLS-0070d-credentials/README.md updated from https://stackedit.io/ --- XLS-0070d-credentials/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/XLS-0070d-credentials/README.md b/XLS-0070d-credentials/README.md index 72b15d80..984a347e 100644 --- a/XLS-0070d-credentials/README.md +++ b/XLS-0070d-credentials/README.md @@ -329,7 +329,7 @@ Transactions that accept this field: * Has not been accepted. * Isn't a credential issued to the `Account` sending the transaction. * `CredentialIDs` is included, but the destination doesn't have Deposit Authorization set up, or the transaction doesn't have a destination (e.g. `AccountSet`). -* The group of `CredentialIDs` are not authorized by the destination. +* The group of `CredentialIDs` is not authorized by the destination. Note: the transaction will still fail if too many credentials are included. The exact list must be provided. From fd887d0f7a1a12a5dc033be6da555dba6efae3f9 Mon Sep 17 00:00:00 2001 From: Mayukha Vadari Date: Fri, 23 Aug 2024 15:22:37 -0400 Subject: [PATCH 12/26] XLS-0070d-credentials/README.md updated from https://stackedit.io/ --- XLS-0070d-credentials/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/XLS-0070d-credentials/README.md b/XLS-0070d-credentials/README.md index 984a347e..4b124a29 100644 --- a/XLS-0070d-credentials/README.md +++ b/XLS-0070d-credentials/README.md @@ -134,7 +134,7 @@ We propose these modifications: | Field Name | Required? | JSON Type | Internal Type | Description | |------------|-----------|-----------|---------------|-------------| -|`Authorize`| |`string`|`AccountID`|The account that received the preauthorization. (The sender of the preauthorized payments.)| +|`Authorize`| |`string`|`AccountID`|This field already exists, but is becoming optional.| |`AuthorizeCredentials`| |`array`|`STArray`|The credential that received the preauthorization. (Any account with this credential can send preauthorized payments).| #### 3.1.1. Object ID From 4f7db237b2e522410e74d091d69afcfd4c1af175 Mon Sep 17 00:00:00 2001 From: Mayukha Vadari Date: Fri, 23 Aug 2024 15:22:52 -0400 Subject: [PATCH 13/26] XLS-0070d-credentials/README.md updated from https://stackedit.io/ --- XLS-0070d-credentials/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/XLS-0070d-credentials/README.md b/XLS-0070d-credentials/README.md index 4b124a29..32fea9b3 100644 --- a/XLS-0070d-credentials/README.md +++ b/XLS-0070d-credentials/README.md @@ -135,7 +135,7 @@ We propose these modifications: | Field Name | Required? | JSON Type | Internal Type | Description | |------------|-----------|-----------|---------------|-------------| |`Authorize`| |`string`|`AccountID`|This field already exists, but is becoming optional.| -|`AuthorizeCredentials`| |`array`|`STArray`|The credential that received the preauthorization. (Any account with this credential can send preauthorized payments).| +|`AuthorizeCredentials`| |`array`|`STArray`|The credential(s) that received the preauthorization. (Any account with these credentials can send preauthorized payments).| #### 3.1.1. Object ID From 6eec8bb4c6a1eff35fc89bc7453d7d2c9b463a75 Mon Sep 17 00:00:00 2001 From: Mayukha Vadari Date: Fri, 23 Aug 2024 15:25:14 -0400 Subject: [PATCH 14/26] XLS-0070d-credentials/README.md updated from https://stackedit.io/ --- XLS-0070d-credentials/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/XLS-0070d-credentials/README.md b/XLS-0070d-credentials/README.md index 32fea9b3..025352a6 100644 --- a/XLS-0070d-credentials/README.md +++ b/XLS-0070d-credentials/README.md @@ -143,7 +143,7 @@ The ID of this object will be either a hash of the `Account` and `Authorize` fie #### 3.1.2. `Authorize` -This field is now optional, and a valid `DepositPreauth` object must either have the `Authorize` field or the `AuthorizeCredentials` field. +This field is now optional, and a valid `DepositPreauth` object must have **exactly one of** the `Authorize` field or the `AuthorizeCredentials` field. #### 3.1.3. `AuthorizeCredentials` From 60e6a1f90f5b1a16417bb7f4cc70f4085f1c5a02 Mon Sep 17 00:00:00 2001 From: Mayukha Vadari Date: Fri, 23 Aug 2024 15:27:23 -0400 Subject: [PATCH 15/26] XLS-0070d-credentials/README.md updated from https://stackedit.io/ --- XLS-0070d-credentials/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/XLS-0070d-credentials/README.md b/XLS-0070d-credentials/README.md index 025352a6..d7fc9c9e 100644 --- a/XLS-0070d-credentials/README.md +++ b/XLS-0070d-credentials/README.md @@ -151,7 +151,7 @@ This field is an array of inner objects. The contents of these inner objects det If more than one credential is included in the list, all of those credentials must be included (effectively ANDing them together). -The list has a maximum size of 8 credentials. +The list has a minimum size of 1 and maximum size of 8 credentials. | Field Name | Required? | JSON Type | Internal Type | Description | |------------|-----------|-----------|---------------|-------------| From 58082c2e2a39fe273808599959ff78f7a883a8fb Mon Sep 17 00:00:00 2001 From: Mayukha Vadari Date: Fri, 23 Aug 2024 15:33:48 -0400 Subject: [PATCH 16/26] XLS-0070d-credentials/README.md updated from https://stackedit.io/ --- XLS-0070d-credentials/README.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/XLS-0070d-credentials/README.md b/XLS-0070d-credentials/README.md index d7fc9c9e..0518b9a4 100644 --- a/XLS-0070d-credentials/README.md +++ b/XLS-0070d-credentials/README.md @@ -151,7 +151,7 @@ This field is an array of inner objects. The contents of these inner objects det If more than one credential is included in the list, all of those credentials must be included (effectively ANDing them together). -The list has a minimum size of 1 and maximum size of 8 credentials. +The list has a minimum size of 1 and a maximum size of 8 credentials. | Field Name | Required? | JSON Type | Internal Type | Description | |------------|-----------|-----------|---------------|-------------| @@ -179,6 +179,8 @@ This proposal adds two new fields: |`AuthorizeCredentials`| |`array`|`STArray`|The credential(s) to preauthorize. | |`UnauthorizeCredentials` | |`array`|`STArray`|The credential(s) whose preauthorization should be revoked.| +**Exactly one of** the `Authorize`, `Unauthorize`, `AuthorizeCredentials`, and `UnauthorizeCredentials` fields must be included. + #### 4.1.1. `AuthorizeCredentials` and `UnauthorizeCredentials` These fields follow the same rules outlined in section 3.1.3 for the `Credential` object's `AuthorizeCredentials` field. @@ -222,16 +224,17 @@ There are two possible methods of doing so: #### 5.1.1. `Subject` and `Issuer` -Only one of these two fields must be specified. If `Subject` is specified, `Account` is the issuer. If `Issuer` is specified, `Account` is the subject. +Exactly one of these two fields must be specified. If `Subject` is specified, `Account` is the issuer. If `Issuer` is specified, `Account` is the subject. #### 5.1.2. `Signature` -If the subject is submitting the account, a signature must be included from the issuer attesting to the credential. This signature will sign a simple JSON that looks something like this: +If the subject is submitting the account, a signature must be included from the issuer attesting to the credential. This signature will sign an encoded object that looks something like this: ```typescript { Issuer: "rISABEL......", Subject: "rALICE.......", CredentialType: "123ABC", + Expiration: 12345678, // if applicable } ``` @@ -340,7 +343,7 @@ Note: the transaction will still fail if too many credentials are included. The ## 9. RPC: `deposit_authorized` -The [`deposit_authorized` RPC method](https://xrpl.org/deposit_authorized.html) already exists on the XRPL. This proposal suggests some modifications to also support permissioned DEX domains. +The [`deposit_authorized` RPC method](https://xrpl.org/deposit_authorized.html) already exists on the XRPL. This proposal suggests some modifications to also support credential authorization. ### 9.1. Request Fields From 5875738fcf76640ec4228e8ec4a366445e598245 Mon Sep 17 00:00:00 2001 From: Mayukha Vadari Date: Fri, 23 Aug 2024 15:35:21 -0400 Subject: [PATCH 17/26] XLS-0070d-credentials/README.md updated from https://stackedit.io/ --- XLS-0070d-credentials/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/XLS-0070d-credentials/README.md b/XLS-0070d-credentials/README.md index 0518b9a4..bba0dd77 100644 --- a/XLS-0070d-credentials/README.md +++ b/XLS-0070d-credentials/README.md @@ -241,7 +241,7 @@ If the subject is submitting the account, a signature must be included from the ### 5.2. Failure Conditions * Both or neither `Subject` and `Issuer` are specified (i.e. there must be only one of the two fields). -* The account in `Subject`/`Issuer` doesn't exist. +* The account in `Subject` doesn't exist. * `Issuer` is included but `Signature` is not. * The time in `Expiration` is in the past. * The `URI` field is too long (limit 256 bytes). @@ -570,7 +570,7 @@ It's much faster to have the credential ID included - it's easy to make sure tha Yes, even if they still have issued credentials in existence. -### A.8: Does a credential issue have to have an on-chain account? +### A.8: Does a credential issuer have to have an on-chain account? No, though they must have a valid keypair. If the second method of creating a credential is used (via a signature from the issuer), the issuer can still attest to a credential without having to have an account on-chain. This is to ensure closer compliance with the W3C Verifiable Credentials spec (see section 9). From 5fc1295c3993cac0a04b6df9e210647076ec1671 Mon Sep 17 00:00:00 2001 From: Mayukha Vadari Date: Tue, 3 Sep 2024 12:02:21 -0400 Subject: [PATCH 18/26] XLS-0070d-credentials/README.md updated from https://stackedit.io/ --- XLS-0070d-credentials/README.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/XLS-0070d-credentials/README.md b/XLS-0070d-credentials/README.md index bba0dd77..b4e303e5 100644 --- a/XLS-0070d-credentials/README.md +++ b/XLS-0070d-credentials/README.md @@ -218,6 +218,7 @@ There are two possible methods of doing so: |`Subject`| |`string`|`AccountID`|The subject of the credential.| |`Issuer`| |`string`|`AccountID`|The issuer of the credential.| |`CredentialType`|✔️|`string`|`Blob`|A (hex-encoded) value to identify the type of credential from the issuer.| +|`IssuerPubKey`| |`string`|`AccountID`|The public key of the issuer.| |`Signature`| |`string`|`Blob`|A signature from the issuer attesting to the credential.| |`Expiration`| |`number`|`UInt32`|Optional credential expiration.| |`URI`| |`string`|`Blob`|Optional additional data about the credential (such as a link to the VC document).| @@ -226,9 +227,11 @@ There are two possible methods of doing so: Exactly one of these two fields must be specified. If `Subject` is specified, `Account` is the issuer. If `Issuer` is specified, `Account` is the subject. -#### 5.1.2. `Signature` +If `Issuer` is specified, `IssuerPubKey` and `Signature` must also be included. If `Subject` is specified, then those two fields must not be included. -If the subject is submitting the account, a signature must be included from the issuer attesting to the credential. This signature will sign an encoded object that looks something like this: +#### 5.1.2. `IssuerPubKey` and `Signature` + +If the subject is submitting the account, a signature (and the corresponding public key) must be included from the issuer attesting to the credential. This signature will sign an encoded object that looks something like this: ```typescript { Issuer: "rISABEL......", From 2b0ac7dfb5f51b1c6862cab4bd1534d98df36e11 Mon Sep 17 00:00:00 2001 From: Mayukha Vadari Date: Tue, 3 Sep 2024 13:27:13 -0400 Subject: [PATCH 19/26] XLS-0070d-credentials/README.md updated from https://stackedit.io/ --- XLS-0070d-credentials/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/XLS-0070d-credentials/README.md b/XLS-0070d-credentials/README.md index b4e303e5..e647ee46 100644 --- a/XLS-0070d-credentials/README.md +++ b/XLS-0070d-credentials/README.md @@ -237,6 +237,7 @@ If the subject is submitting the account, a signature (and the corresponding pub Issuer: "rISABEL......", Subject: "rALICE.......", CredentialType: "123ABC", + URI: "example.com", // will be in hex Expiration: 12345678, // if applicable } ``` From 67bd79173876cf1fcc121c4406f085d45c1e880e Mon Sep 17 00:00:00 2001 From: Mayukha Vadari Date: Mon, 9 Sep 2024 11:47:06 -0400 Subject: [PATCH 20/26] XLS-0070d-credentials/README.md updated from https://stackedit.io/ --- XLS-0070d-credentials/README.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/XLS-0070d-credentials/README.md b/XLS-0070d-credentials/README.md index e647ee46..5438ad0b 100644 --- a/XLS-0070d-credentials/README.md +++ b/XLS-0070d-credentials/README.md @@ -97,13 +97,15 @@ The ID of this object will be a hash that incorporates the `Subject`, `Issuer`, |-----------|------------| |`lsfAccepted`|`0x00010000`| -`lsfAccepted` is on if the subject of the credential has accepted the credential. If it is off, the issuer has the reserve burden; if it is on, the burden moves to the subject. +The `lsfAccepted` flag represents whether the subject of the credential has accepted the credential. If this flag is disabled, the issuer is responsible for this ledger entry's reserve; if the flag is enabled, the subject of the credential is responsible for the reserve instead. This flag is disabled by default, but is enabled as the result of a successful `CredentialAccept` transaction, or if the secondary signing flow is used to create the credential. + +A credential should not be considered "valid" until it has been accepted. #### 2.1.3. `CredentialType` This value is similar to the NFT `Taxon` value, where the value's meaning will be decided by the issuer. It may be the same as a claim in a VC, but could also represent a subset of such a claim. -It has a maximum length of 256 bytes. +It has a maximum length of 256 bytes, and cannot be an empty string. ### 2.2. Account Deletion @@ -255,7 +257,8 @@ If the subject is submitting the account, a signature (and the corresponding pub If the transaction is successful: * The `Credential` object is created. -* If `Issuer` == `Account`, then the `lsfAccepted` flag is enabled. +* If `Issuer` is specified (i.e. the subject is creating the credential with the issuer's permission), then the `lsfAccepted` flag is enabled. +* If `Subject` === `Account` (i.e. the subject and issuer are the same account), then the `lsfAccepted` flag is enabled. ## 6. Transaction: `CredentialAccept` From 866a67c2565d7a8a23e49107b9924b99fc240b00 Mon Sep 17 00:00:00 2001 From: Mayukha Vadari Date: Mon, 9 Sep 2024 11:52:34 -0400 Subject: [PATCH 21/26] XLS-0070d-credentials/README.md updated from https://stackedit.io/ --- XLS-0070d-credentials/README.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/XLS-0070d-credentials/README.md b/XLS-0070d-credentials/README.md index 5438ad0b..1e628bac 100644 --- a/XLS-0070d-credentials/README.md +++ b/XLS-0070d-credentials/README.md @@ -262,7 +262,7 @@ If the transaction is successful: ## 6. Transaction: `CredentialAccept` -This transaction transfers a credential from the `Issuer` to the `Account`. It is not a valid credential until it has been transferred. +This transaction accepts a credential issued to the `Account`. The credential is not considered valid until it has been transferred/accepted. ### 6.1. Fields @@ -295,6 +295,8 @@ It can be executed by: * The account, anytime. * Anyone, after the expiration time is up. +Deleting a credential is also how a credential is un-accepted. + ### 7.1. Fields | Field Name | Required? | JSON Type | Internal Type | Description | @@ -308,7 +310,7 @@ It can be executed by: ### 7.2. Failure Conditions * The credential described by the `Subject`, `Issuer`, and `CredentialType` fields doesn't exist. -* The `Account` isn't the issuer or account, and the expiration hasn't passed. +* The `Account` isn't the issuer or subject, and the expiration hasn't passed. ### 7.3. State Changes @@ -435,7 +437,7 @@ This is the object created by the `CredentialCreate` transaction. Flags: 0, Subject: "rALICE.......", Issuer: "rISABEL......", - CredentialType: "123ABC", + CredentialType: "4B5943", // "KYC" in hex Expiration: 789004799, // the end of the year URI: "isabel.com/credentials/kyc/alice" // This will be converted into hex } @@ -450,7 +452,7 @@ Alice accepts the credential, thereby making it valid. TransactionType: "CredentialAccept", Account: "rALICE.......", Issuer: "rISABEL......", - CredentialType: "123ABC" + CredentialType: "4B5943" } ``` From 10e1718dd6ef32d6cb9d75ef7f0284cb097cb08a Mon Sep 17 00:00:00 2001 From: Mayukha Vadari Date: Mon, 9 Sep 2024 12:17:30 -0400 Subject: [PATCH 22/26] XLS-0070d-credentials/README.md updated from https://stackedit.io/ From f7cf7dd54c8d2d4eb8aac0f69844b1bb62bbc765 Mon Sep 17 00:00:00 2001 From: Mayukha Vadari Date: Tue, 10 Sep 2024 13:43:17 -0400 Subject: [PATCH 23/26] XLS-0070d-credentials/README.md updated from https://stackedit.io/ --- XLS-0070d-credentials/README.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/XLS-0070d-credentials/README.md b/XLS-0070d-credentials/README.md index 1e628bac..03dff722 100644 --- a/XLS-0070d-credentials/README.md +++ b/XLS-0070d-credentials/README.md @@ -317,21 +317,22 @@ Deleting a credential is also how a credential is un-accepted. If the transaction is successful: * The `Credential` object is deleted. -## 8. Transactions: Common Fields +## 8. Any Transaction Affected by Deposit Authorization ### 8.1. Fields As a reference, [here](https://xrpl.org/docs/references/protocol/transactions/common-fields/) are the fields that all transactions currently have. - +The transactions that this field will be added to are: +* `Payment` +* `EscrowFinish` +* `PaymentChannelClaim` +* `AccountDelete` | Field Name | Required? | JSON Type | Internal Type | |------------|-----------|-----------|---------------| |`CredentialIDs`| |`array`|`Vector256`|Credential(s) to attach to the transaction.| -Transactions that accept this field: -* Basically anything with a `Destination` field (like a payment) or something that has to be accepted by the destination (like an escrow/check). - ### 8.2. Failure Conditions * Any of the `CredentialIDs`: From a66494d94f9dcfc3f28077f58a553854dd55a5f1 Mon Sep 17 00:00:00 2001 From: Mayukha Vadari Date: Tue, 10 Sep 2024 14:55:48 -0400 Subject: [PATCH 24/26] XLS-0070d-credentials/README.md updated from https://stackedit.io/ --- XLS-0070d-credentials/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/XLS-0070d-credentials/README.md b/XLS-0070d-credentials/README.md index 03dff722..3f385845 100644 --- a/XLS-0070d-credentials/README.md +++ b/XLS-0070d-credentials/README.md @@ -30,6 +30,7 @@ We propose: * Creating a `CredentialCreate` transaction type * Creating a `CredentialAccept` transaction type * Creating a `CredentialDelete` transaction type +* Modifying other transactions that are affected by Deposit Authorization This feature will require an amendment, tentatively titled `CredentialAuth`. From a795b4b34570c05521cd24cb2e1e40092bd1c86b Mon Sep 17 00:00:00 2001 From: Mayukha Vadari Date: Tue, 10 Sep 2024 15:56:15 -0400 Subject: [PATCH 25/26] XLS-0070d-credentials/README.md updated from https://stackedit.io/ --- XLS-0070d-credentials/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/XLS-0070d-credentials/README.md b/XLS-0070d-credentials/README.md index 3f385845..995d396c 100644 --- a/XLS-0070d-credentials/README.md +++ b/XLS-0070d-credentials/README.md @@ -308,6 +308,8 @@ Deleting a credential is also how a credential is un-accepted. |`Issuer`| |`string`|`AccountID`|The issuer of the credential. If omitted, `Account` is assumed to be the issuer.| |`CredentialType`|✔️|`string`|`Blob`|A (hex-encoded) value to identify the type of credential from the issuer.| +_Note: If an account is deleting a credential it issued to itself, then either `Subject` or `Issuer` can be specified, but at least one must be._ + ### 7.2. Failure Conditions * The credential described by the `Subject`, `Issuer`, and `CredentialType` fields doesn't exist. From 74b3441f5a5b772e2a6acaf30c27a9c7fe0f98da Mon Sep 17 00:00:00 2001 From: Mayukha Vadari Date: Wed, 11 Sep 2024 10:39:25 -0400 Subject: [PATCH 26/26] XLS-0070d-credentials/README.md updated from https://stackedit.io/ --- XLS-0070d-credentials/README.md | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/XLS-0070d-credentials/README.md b/XLS-0070d-credentials/README.md index 995d396c..42a01013 100644 --- a/XLS-0070d-credentials/README.md +++ b/XLS-0070d-credentials/README.md @@ -140,15 +140,13 @@ We propose these modifications: |`Authorize`| |`string`|`AccountID`|This field already exists, but is becoming optional.| |`AuthorizeCredentials`| |`array`|`STArray`|The credential(s) that received the preauthorization. (Any account with these credentials can send preauthorized payments).| +A valid `DepositPreauth` object must have **exactly one of** the `Authorize` field or the `AuthorizeCredentials` field. + #### 3.1.1. Object ID The ID of this object will be either a hash of the `Account` and `Authorize` fields (as it currently is), or a hash of the `Account` and the contents of `AuthorizeCredentials` fields, combined with the unique space key for `DepositAuth` objects: `0x0070`. -#### 3.1.2. `Authorize` - -This field is now optional, and a valid `DepositPreauth` object must have **exactly one of** the `Authorize` field or the `AuthorizeCredentials` field. - -#### 3.1.3. `AuthorizeCredentials` +#### 3.1.2. `AuthorizeCredentials` This field is an array of inner objects. The contents of these inner objects determine the credential(s) that are accepted.