From 1d381a9b15048ec38ec371b3debcb965b28af847 Mon Sep 17 00:00:00 2001 From: Amarantha Kulkarni Date: Wed, 17 Jul 2024 13:05:11 -0700 Subject: [PATCH 01/10] Create source file account-types.md --- account-types.md | 84 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 account-types.md diff --git a/account-types.md b/account-types.md new file mode 100644 index 00000000000..f2ba789b7c3 --- /dev/null +++ b/account-types.md @@ -0,0 +1,84 @@ +--- +html: account-types.html +parent: accounts.html +seo: + description: Businesses sending transactions on the XRP Ledger automatically should set up separate addresses for different purposes to minimize risk. +labels: + - Tokens + - Security +--- +# Account Types + +{% partial file="/docs/_snippets/issuing-and-operational-addresses-intro.md" /%} + + +## Funds Lifecycle + +When a token issuer follows this separation of roles, funds tend to flow in specific directions, as in the following diagram: + +[{% inline-svg file="/docs/img/issued-currency-funds-flow.svg" /%}](/docs/img/issued-currency-funds-flow.svg "Diagram: Funds flow from the issuing address to standby addresses, to operational addresses, to customer and partner addresses, and finally back to the issuing address.") + +The issuing address creates tokens by sending payments to standby addresses. These tokens have negative value from the perspective of the issuing address, since they (often) represent obligations. The same tokens have positive value from other perspectives, including from the perspective of a standby address. + +The standby addresses, which are operated by actual humans, send those tokens to operational addresses. This step allows the issuing address to be used as little as possible after this point, while having at least some tokens available on standby. + +Operational addresses, which are operated by automated systems, send payments to other counterparties, such as liquidity providers, partners, and other customers. Those counterparties may send funds freely among themselves multiple times. + +As always, token payments must "ripple through" the issuer across trust lines. + +Eventually, someone sends tokens back to the issuer. This destroys those tokens, reducing the issuer's obligations in the XRP Ledger. If the token is a stablecoin, this is the first step of redeeming the tokens for the corresponding off-ledger assets. + + +## Issuing Address + +The issuing address is like a vault. Partners, customers, and operational addresses create trust lines to the issuing address, but this address sends as few transactions as possible. Periodically, a human operator creates and signs a transaction from the issuing address to refill the balances of a standby or operational address. Ideally, the secret key used to sign these transactions should never be accessible from any internet-connected computer. + +Unlike a vault, the issuing address can receive payments directly from customers and partners. Since all transactions in the XRP Ledger are public, automated systems can watch for payments to the issuing address without needing a secret key. + +### Issuing Address Compromise + +If a malicious actor learns the secret key behind a institution's issuing address, that actor can create new tokens and send them to users or trade them in the decentralized exchange. This can make a stablecoin issuer insolvent. It can become difficult for the financial institution to distinguish legitimately-obtained tokens and redeem them fairly. If a financial institution loses control of its issuing address, the institution must create a new issuing address, and all users who have trust lines to the old issuing address must create new trust lines with the new address. + +### Multiple Issuing Addresses + +A financial institution can issue more than one type of token in the XRP Ledger from a single issuing address. However, there are some settings that apply equally to all (fungible) tokens issued from an address, including the percentage for [transfer fees](../tokens/transfer-fees.md) and the [global freeze](../tokens/fungible-tokens/freezes.md) status. If the financial institution wants the flexibility to manage settings differently for each type of token, the institution must multiple issuing addresses. + + +## Operational Addresses + +An operational address is like a cash register. It makes payments on behalf of the institution by transferring tokens to customers and partners. To sign transactions automatically, the secret key for an operational address must be stored on a server that is connected to the internet. (The secret key can be stored encrypted, but the server must decrypt it to sign transactions.) Customers and partners do not, and should not, create trust lines to an operational address. + +Each operational address has a limited balance of tokens and XRP. When the balance of an operational address gets low, the financial institution refills it by sending a payment from the issuing address or a standby address. + +### Operational Address Compromise + +If a malicious actor learns the secret key behind an operational address, the financial institution can only lose as much as that operational address holds. The institution can switch to a new operational address with no action from customers and partners. + + +## Standby Addresses + +Another optional step that an institution can take to balance risk and convenience is to use "standby addresses" as an intermediate step between the issuing address and operational addresses. The institution can fund additional XRP Ledger addresses as standby addresses, whose keys are not available to always-online servers, but are entrusted to different trusted users. + +When an operational address is running low on funds (either tokens or XRP), a trusted user can use a standby address to refill the operational address's balance. When a standby addresses run low on funds, the institution can use the issuing address to send more funds to a standby address in a single transaction, and the standby addresses can distribute those funds among themselves if necessary. This improves security of the issuing address, allowing it to make fewer total transactions, without leaving too much money in the control of a single automated system. + +As with operational addresses, a standby address must have an accounting relationship with the issuing address, and not with customers or partners. All precautions that apply to operational addresses also apply to standby addresses. + +### Standby Address Compromise + +If a standby address is compromised, the consequences are like an operational address being compromised. A malicious actor can steal any balances possessed by the standby address, and the financial institution can change to a new standby address with no action from customers and partners. + + +## See Also + +- **Concepts:** + - [Accounts](index.md) + - [Cryptographic Keys](cryptographic-keys.md) +- **Tutorials:** + - [Assign a Regular Key Pair](../../tutorials/how-tos/manage-account-settings/assign-a-regular-key-pair.md) + - [Change or Remove a Regular Key Pair](../../tutorials/how-tos/manage-account-settings/change-or-remove-a-regular-key-pair.md) +- **References:** + - [account_info method][] + - [SetRegularKey transaction][] + - [AccountRoot object](../../references/protocol/ledger-data/ledger-entry-types/accountroot.md) + +{% raw-partial file="/docs/_snippets/common-links.md" /%} From 2b4275e864817dda21d9a35d4b0c38f240dc529d Mon Sep 17 00:00:00 2001 From: Amarantha Kulkarni Date: Wed, 17 Jul 2024 13:05:12 -0700 Subject: [PATCH 02/10] Create source file addresses.md --- addresses.md | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 addresses.md diff --git a/addresses.md b/addresses.md new file mode 100644 index 00000000000..e9b7d8a4323 --- /dev/null +++ b/addresses.md @@ -0,0 +1,96 @@ +--- +html: addresses.html +parent: accounts.html +seo: + description: Addresses uniquely identify XRP Ledger accounts, using base58 format. +labels: + - Accounts +--- +# Addresses + +{% partial file="/docs/_snippets/data_types/address.md" /%} + +Any valid address can [become an account in the XRP Ledger](index.md#creating-accounts) by being funded. You can also use an address that has not been funded to represent a [regular key](cryptographic-keys.md) or a member of a [signer list](multi-signing.md). Only a funded account can be the sender of a transaction. + +Creating a valid address is a strictly mathematical task starting with a key pair. You can generate a key pair and calculate its address entirely offline without communicating to the XRP Ledger or any other party. The conversion from a public key to an address involves a one-way hash function, so it is possible to confirm that a public key matches an address but it is impossible to derive the public key from the address alone. (This is part of the reason why signed transactions include the public key _and_ the address of the sender.) + + +## Special Addresses + +Some addresses have special meaning, or historical uses, in the XRP Ledger. In many cases, these are "black hole" addresses, meaning the address is not derived from a known secret key. Since it is effectively impossible to guess a secret key from only an address, any XRP possessed by black hole addresses is lost forever. + + +| Address | Name | Meaning | Black Hole? | +|-------------------------------|------|---------|-------------| +| `rrrrrrrrrrrrrrrrrrrrrhoLvTp` | ACCOUNT\_ZERO | An address that is the XRP Ledger's [base58][] encoding of the value `0`. In peer-to-peer communications, `rippled` uses this address as the issuer for XRP. | Yes | +| `rrrrrrrrrrrrrrrrrrrrBZbvji` | ACCOUNT\_ONE | An address that is the XRP Ledger's [base58][] encoding of the value `1`. In the ledger, [RippleState entries](../../references/protocol/ledger-data/ledger-entry-types/ripplestate.md) use this address as a placeholder for the issuer of a trust line balance. | Yes | +| `rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh` | The genesis account | When `rippled` starts a new genesis ledger from scratch (for example, in stand-alone mode), this account holds all the XRP. This address is generated from the seed value `masterpassphrase` which is [hard-coded](https://github.com/XRPLF/rippled/blob/94ed5b3a53077d815ad0dd65d490c8d37a147361/src/ripple/app/ledger/Ledger.cpp#L184). | No | +| `rrrrrrrrrrrrrrrrrNAMEtxvNvQ` | Ripple Name reservation black-hole | In the past, Ripple asked users to send XRP to this account to reserve Ripple Names.| Yes | +| `rrrrrrrrrrrrrrrrrrrn5RM1rHd` | NaN Address | Previous versions of [ripple-lib](https://github.com/XRPLF/xrpl.js) generated this address when encoding the value [NaN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/NaN) using the XRP Ledger's [base58][] string encoding format. | Yes | + + +## Address Encoding + +**Tip:** These technical details are only relevant for people building low-level library software for XRP Ledger compatibility! + +[[Source]](https://github.com/XRPLF/rippled/blob/35fa20a110e3d43ffc1e9e664fc9017b6f2747ae/src/ripple/protocol/impl/AccountID.cpp#L109-L140 "Source") + +XRP Ledger addresses are encoded using [base58][] with the _dictionary_ `rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz`. Since the XRP Ledger encodes several types of keys with base58, it prefixes the encoded data with a one-byte "type prefix" (also called a "version prefix") to distinguish them. The type prefix causes addresses to usually start with different letters in base58 format. + +The following diagram shows the relationship between keys and addresses: + +[{% inline-svg file="/docs/img/address-encoding.svg" /%}](/docs/img/address-encoding.svg "Master Public Key + Type Prefix → Account ID + Checksum → Address") + +The formula for calculating an XRP Ledger address from a public key is as follows. For the complete example code, see [`encode_address.js`](https://github.com/XRPLF/xrpl-dev-portal/blob/master/_code-samples/address_encoding/js/encode_address.js). For the process of deriving a public key from a passphrase or seed value, see [Key Derivation](cryptographic-keys.md#key-derivation). + +1. Import required algorithms: SHA-256, RIPEMD160, and base58. Set the dictionary for base58. + + ``` + 'use strict'; + const assert = require('assert'); + const crypto = require('crypto'); + const R_B58_DICT = 'rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz'; + const base58 = require('base-x')(R_B58_DICT); + + assert(crypto.getHashes().includes('sha256')); + assert(crypto.getHashes().includes('ripemd160')); + ``` + +2. Start with a 33-byte ECDSA secp256k1 public key, or a 32-byte Ed25519 public key. For Ed25519 keys, prefix the key with the byte `0xED`. + + ``` + const pubkey_hex = + 'ED9434799226374926EDA3B54B1B461B4ABF7237962EAE18528FEA67595397FA32'; + const pubkey = Buffer.from(pubkey_hex, 'hex'); + assert(pubkey.length == 33); + ``` + +3. Calculate the [RIPEMD160](https://en.wikipedia.org/wiki/RIPEMD) hash of the SHA-256 hash of the public key. This value is the "Account ID". + + ``` + const pubkey_inner_hash = crypto.createHash('sha256').update(pubkey); + const pubkey_outer_hash = crypto.createHash('ripemd160'); + pubkey_outer_hash.update(pubkey_inner_hash.digest()); + const account_id = pubkey_outer_hash.digest(); + ``` + +4. Calculate the SHA-256 hash of the SHA-256 hash of the Account ID; take the first 4 bytes. This value is the "checksum". + + ``` + const address_type_prefix = Buffer.from([0x00]); + const payload = Buffer.concat([address_type_prefix, account_id]); + const chksum_hash1 = crypto.createHash('sha256').update(payload).digest(); + const chksum_hash2 = crypto.createHash('sha256').update(chksum_hash1).digest(); + const checksum = chksum_hash2.slice(0,4); + ``` + +5. Concatenate the payload and the checksum. Calculate the base58 value of the concatenated buffer. The result is the address. + + ``` + const dataToEncode = Buffer.concat([payload, checksum]); + const address = base58.encode(dataToEncode); + console.log(address); + // rDTXLQ7ZKZVKz33zJbHjgVShjsBnqMBhmN + ``` + +{% raw-partial file="/docs/_snippets/common-links.md" /%} From c1b403f992bb3fca72caf9f871a47d9224a34782 Mon Sep 17 00:00:00 2001 From: Amarantha Kulkarni Date: Wed, 17 Jul 2024 13:05:13 -0700 Subject: [PATCH 03/10] Create source file cryptographic-keys.md --- cryptographic-keys.md | 259 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 259 insertions(+) create mode 100644 cryptographic-keys.md diff --git a/cryptographic-keys.md b/cryptographic-keys.md new file mode 100644 index 00000000000..0cb1d94f0bf --- /dev/null +++ b/cryptographic-keys.md @@ -0,0 +1,259 @@ +--- +html: cryptographic-keys.html +parent: accounts.html +seo: + description: Use cryptographic keys to approve transactions so the XRP Ledger can execute them. +labels: + - Smart Contracts + - Security +--- +# Cryptographic Keys + +In the XRP Ledger, a digital signature _authorizes_ a [transaction](../transactions/index.md) to do a specific set of actions. Only signed transactions can be submitted to the network and included in a validated ledger. + +To make a digital signature, you use a cryptographic key pair associated with the transaction's sending account. A key pair may be generated using any of the XRP Ledger's supported [cryptographic signing algorithms](#signing-algorithms). A key pair can be used as a [master key pair](#master-key-pair), [regular key pair](#regular-key-pair) or a member of a [signer list](multi-signing.md), regardless of what algorithm was used to generate it. + +**Warning:** It is important to maintain proper security over your cryptographic keys. Digital signatures are the only way of authorizing transactions in the XRP Ledger, and there is no privileged administrator who can undo or reverse any transactions after they have applied. If someone else knows the seed or private key of your XRP Ledger account, that person can create digital signatures to authorize any transaction the same as you could. + +## Generating Keys + +Many [client libraries](../../references/client-libraries.md) and applications can generate a key pair suitable for use with the XRP Ledger. However, you should only use key pairs that were generated with devices and software you trust. Compromised applications can expose your secret to malicious users who can then send transactions from your account later. + + +## Key Components + +A cryptographic key pair is a **private key** and a **public key** that are connected mathematically through a key derivation process. Each key is a number; the private key should be chosen using a strong source of randomness. The [cryptographic signing algorithm](#signing-algorithms) defines the key derivation process and sets constraints on the numbers that can be cryptographic keys. + +When dealing with the XRP Ledger, you may also use some related values such as a passphrase, seed, account ID, or address. + +[{% inline-svg file="/docs/img/cryptographic-keys.svg" /%}](/docs/img/cryptographic-keys.svg "Diagram: Passphrase → Seed → Private Key → Public Key → Account ID ←→ Address") +_Figure: A simplified view of the relationship between cryptographic key values._ + +The passphrase, seed, and private key are **secrets**: if you know any of these values for an account, you can make valid signatures and you have full control over that account. If you own an account, be **very careful** with your account's secret information. If you don't have it, you can't use your account. If someone else can access it, they can take control of your account. + +The public key, account ID, and address are public information. There are some situations where you might temporarily keep a public key to yourself, but eventually you need to publish it as part of a transaction so that the XRP Ledger can verify the signature and process the transaction. + +For more technical details of how key derivation works, see [Key Derivation](#key-derivation). + +### Passphrase + +You can, optionally, use a passphrase or some other input as a way of choosing a seed or private key. This is less secure than choosing the seed or private key completely at random, but there are some rare cases where you want to do this. (For example, in 2018 "XRPuzzler" gave away XRP to the first person [to solve a puzzle](https://bitcoinexchangeguide.com/cryptographic-puzzle-creator-xrpuzzler-offers-137-xrp-reward-to-anyone-who-can-solve-it/); he used the puzzle's solution as the passphrase to an account holding the prize XRP.) + +The passphrase is secret information, so you must protect it very carefully. Anyone who knows an address's passphrase has effectively full control over the address. + +### Seed + +A _seed_ value is a compact value that is used to [derive](#key-derivation) the actual private and public keys for an account. In a [wallet_propose method][] response, the `master_key`, `master_seed`, and `master_seed_hex` all represent the same seed value, in various formats. Any of these formats can be used to sign transactions. Despite being prefixed with `master_`, the keys this seed represents are not necessarily the master keys for an account; you can use a key pair as a regular key or a member of a multi-signing list as well. + +The seed value is secret information, so you must protect it very carefully. Anyone who knows an address's seed value has effectively full control over that address. + +### Private Key + +The _private key_ is the value that is used to create a digital signature. Most XRP Ledger software does not explicitly show the private key, and [derives the private key](#key-derivation) from the seed value when necessary. It is technically possible to save the private key instead of the seed and use that to sign transactions directly, but this usage is rare. + +Like the seed, the private key is secret information, so you must protect it very carefully. Anyone who knows an address's private key has effectively full control over that address. + +### Public Key + +The _public key_ is the value used to verify the authenticity of a digital signature. The public key is derived from the private key as part of key derivation. In a [wallet_propose method][] response, the `public_key` and `public_key_hex` both represent the same public key value. + +Transactions in the XRP Ledger must include the public keys so that the network can verify the transactions' signatures. The public key cannot be used to create valid signatures, so it is safe to share publicly. + + +### Account ID and Address + +The **Account ID** is the core identifier for an [account](index.md) or a key pair. It is derived from the public key. In the XRP Ledger protocol, the Account ID is 20 bytes of binary data. Most XRP Ledger APIs represent the Account ID as an address, in one of two formats: + +- A "classic address" writes an Account ID in [base58][] with a checksum. In a [wallet_propose method][] response, this is the `account_id` value. +- An "X-Address" combines an Account ID _and_ a [Destination Tag](../transactions/source-and-destination-tags.md) and writes the combined value in [base58][] with a checksum. + +The checksum in both formats is there so that small changes result in an invalid address, instead of changing it to refer to a different, but still potentially valid, account. This way, if you make a typo or a transmission error occurs, you don't send money to the wrong place. + +It is important to know that not all Account IDs (or addresses) refer to accounts in the ledger. Deriving keys and addresses is purely a mathematical operation. For an account to have a record in the XRP Ledger, it must [receive a payment of XRP](index.md#creating-accounts) that funds its [reserve requirement](reserves.md). An account cannot send any transactions until after it has been funded. + +Even if an Account ID or address does not refer to a funded account, you _can_ use that Account ID or address to represent a [regular key pair](#regular-key-pair) or a [member of a signer list](multi-signing.md). + +### Key Type + +The XRP Ledger supports more than one [cryptographic signing algorithm](#signing-algorithms). Any given key pair is only valid for a specific cryptographic signing algorithm. Some private keys may technically qualify as valid keys for more than one algorithm, but those private keys would have different public keys for each algorithm, and you should not reuse private keys anyway. + +The `key_type` field in the [wallet_propose method][] refers to the cryptographic signing algorithm to use. + + +## Master Key Pair + +The master key pair consists of a private key and a public key. The address of an account is derived from the account's master key pair, so they are intrinsically related. You cannot change or remove the master key pair, but you can disable it. + +The [wallet_propose method][] is one way of generating a master key pair. The response from this method shows the account's seed, address, and master public key together. For some other ways of setting up master key pairs, see [Secure Signing](../transactions/secure-signing.md). + +**Warning:** If a malicious actor learns your master private key (or seed), they have full control over your account, unless your master key pair is disabled. They can take all the money your account holds and do other irreparable harm. Treat your secret values with care! + +Because changing a master key pair is impossible, you should treat it with care proportionate to the value it holds. A good practice is to [keep your master key pair offline](../../tutorials/how-tos/manage-account-settings/offline-account-setup.md) and set up a regular key pair to sign transactions from your account instead. By keeping the master key pair enabled but offline, you can be reasonably certain that no one can get access to it using the internet, but you can still go find it to use in an emergency. + +Keeping your master key pair offline means not putting the secret information (passphrase, seed, or private key) anywhere that malicious actors can get access to it. In general, this means it is not within reach of a computer program that interacts with the internet at large. For example, you could keep it on an air-gapped machine that never connects to the internet, on a piece of paper stored in a safe, or have it completely memorized. (Memorization has some drawbacks, though, including making it impossible to pass the key on after you are dead.) + + + +### Special Permissions + +**Only** the master key pair can authorize transactions to do certain things: + +- Send an account's very first transaction, because accounts cannot be initialized with another way of [authorizing transactions](../transactions/index.md#authorizing-transactions). + +- Disable the master key pair. + +- Permanently give up the ability to [freeze](../tokens/fungible-tokens/freezes.md#no-freeze). + +- Send a special [key reset transaction](../transactions/transaction-cost.md#key-reset-transaction) with a transaction cost of 0 XRP. + +A regular key or [multi-signature](multi-signing.md) can do anything else the same as the master key pair. Notably, after you have disabled the master key pair, you can re-enable it using a regular key pair or multi-signature. You can also [delete an account](deleting-accounts.md) if it meets the requirements for deletion. + + +## Regular Key Pair + +An XRP Ledger account can authorize a secondary key pair, called a _regular key pair_. After doing so, you can use either the [master key pair](#master-key-pair) or the regular key to authorize transactions. You can remove or replace your regular key pair at any time without changing the rest of your account. + +A regular key pair can authorize most of the same types of transactions as the master key pair, with [certain exceptions](#special-permissions). For example, a regular key pair _can_ authorize a transaction to change the regular key pair. + +A good security practice is to save your master private key somewhere offline, and use a regular key pair most of the time. As a precaution, you can change the regular key pair regularly. If a malicious user learns your regular private key, you can get the master key pair out of offline storage and use it to change or remove the regular key pair. This way, you can regain control of your account. Even if you are not fast enough to stop the malicious user from stealing your money, at least you don't need to move to a new account and re-create all your settings and relationships from scratch. + +Regular key pairs have the same format as master key pairs. You generate them the same way (for example, using the [wallet_propose method][]). The only difference is that a regular key pair is not intrinsically tied to the account it signs transactions for. It is possible (but not a good idea) to use the master key pair from one account as the regular key pair for another account. + +The [SetRegularKey transaction][] assigns or changes the regular key pair for an account. For a tutorial on assigning or changing a regular key pair, see [Assign a Regular Key Pair](../../tutorials/how-tos/manage-account-settings/assign-a-regular-key-pair.md). + + +## Signing Algorithms + +Cryptographic key pairs are always tied to a specific signing algorithm, which defines the mathematical relationships between the secret key and the public key. Cryptographic signing algorithms have the property that, given the current state of cryptographic techniques, it is "easy" to use a secret key to calculate a matching public key, but it is effectively impossible to compute a matching secret key by starting from a public key. + +The XRP Ledger supports the following cryptographic signing algorithms: + +| Key Type | Algorithm | Description | +|-------------|-----------|---| +| `secp256k1` | [ECDSA](https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm) using the elliptic curve [secp256k1](https://en.bitcoin.it/wiki/Secp256k1) | This is the same scheme Bitcoin uses. The XRP Ledger uses these key types by default. | +| `ed25519` | [EdDSA](https://tools.ietf.org/html/rfc8032) using the elliptic curve [Ed25519](https://ed25519.cr.yp.to/) | This is a newer algorithm which has better performance and other convenient properties. Since Ed25519 public keys are one byte shorter than secp256k1 keys, `rippled` prefixes Ed25519 public keys with the byte `0xED` so both types of public key are 33 bytes. | + +When you generate a key pair with the [wallet_propose method][], you can specify the `key_type` to choose which cryptographic signing algorithm to use to derive the keys. If you generated a key type other than the default, you must also specify the `key_type` when signing transactions. + +The supported types of key pairs can be used interchangeably throughout the XRP Ledger as master key pairs, regular key pairs, and members of signer lists. The process of [deriving an address](addresses.md#address-encoding) is the same for secp256k1 and Ed25519 key pairs. + + +### Future Algorithms + +In the future, it is likely that the XRP Ledger will need new cryptographic signing algorithms to keep up with developments in cryptography. For example, if quantum computers using [Shor's algorithm](https://en.wikipedia.org/wiki/Shor's_algorithm) (or something similar) will soon be practical enough to break elliptic curve cryptography, XRP Ledger developers can add a cryptographic signing algorithm that isn't easily broken. As of mid 2020, there's no clear first choice "quantum-resistant" signing algorithm and quantum computers are not yet practical enough to be a threat, so there are no immediate plans to add any specific algorithms. + + +## Key Derivation + +The process of deriving a key pair depends on the signing algorithm. In all cases, keys are generated from a _seed_ value that is 16 bytes (128 bits) in length. The seed value can be completely random (recommended) or it can be derived from a specific passphrase by taking the [SHA-512 hash][Hash] and keeping the first 16 bytes (like [SHA-512Half][], but keeping only 128 bits instead of 256 bits of the output). + +### Sample Code + +The key derivation processes described here are implemented in multiple places and programming languages: + +- In C++ in the `rippled` code base: + - [Seed definition](https://github.com/XRPLF/rippled/blob/develop/src/ripple/protocol/Seed.h) + - [General & Ed25519 key derivation](https://github.com/XRPLF/rippled/blob/develop/src/ripple/protocol/impl/SecretKey.cpp) + - [secp256k1 key derivation](https://github.com/XRPLF/rippled/blob/develop/src/ripple/protocol/impl/SecretKey.cpp) +- In Python 3 in {% repo-link path="_code-samples/key-derivation/py/key_derivation.py" %}this repository's code samples section{% /repo-link %}. +- In JavaScript in the [`ripple-keypairs`](https://github.com/XRPLF/xrpl.js/tree/main/packages/ripple-keypairs) package. + +### Ed25519 Key Derivation +[[Source]](https://github.com/XRPLF/rippled/blob/fc7ecd672a3b9748bfea52ce65996e324553c05f/src/ripple/protocol/impl/SecretKey.cpp#L203 "Source") + +[{% inline-svg file="/docs/img/key-derivation-ed25519.svg" /%}](/docs/img/key-derivation-ed25519.svg "Passphrase → Seed → Secret Key → Prefix + Public Key") + +1. Calculate the [SHA-512Half][] of the seed value. The result is the 32-byte secret key. + + **Tip:** All 32-byte numbers are valid Ed25519 secret keys. However, only numbers that are chosen randomly enough are secure enough to be used as secret keys. + +2. To calculate an Ed25519 public key, use the standard public key derivation for [Ed25519](https://ed25519.cr.yp.to/software.html) to derive the 32-byte public key. + + **Caution:** As always with cryptographic algorithms, use a standard, well-known, publicly-audited implementation whenever possible. For example, [OpenSSL](https://www.openssl.org/) has implementations of core Ed25519 and secp256k1 functions. + +3. Prefix the 32-byte public key with the single byte `0xED` to indicate an Ed25519 public key, resulting in 33 bytes. + + If you are implementing code to sign transactions, remove the `0xED` prefix and use the 32-byte key for the actual signing process. + +4. When serializing an account public key to [base58][], use the account public key prefix `0x23`. + + Validator ephemeral keys cannot be Ed25519. + +### secp256k1 Key Derivation +[[Source]](https://github.com/XRPLF/rippled/blob/develop/src/ripple/protocol/impl/SecretKey.cpp "Source") + +[{% inline-svg file="/docs/img/key-derivation-secp256k1.svg" /%}](/docs/img/key-derivation-secp256k1.svg "Passphrase → Seed → Root Key Pair → Intermediate Key Pair → Master Key Pair") + +Key derivation for secp256k1 XRP Ledger account keys involves more steps than Ed25519 key derivation for a couple reasons: + +- Not all 32-byte numbers are valid secp256k1 secret keys. +- The XRP Ledger's reference implementation has an unused, incomplete framework for deriving a family of key pairs from a single seed value. + +The steps to derive the XRP Ledger's secp256k1 account key pair from a seed value are as follows: + +1. Calculate a "root key pair" from the seed value, as follows: + + 1. Concatenate the following in order, for a total of 20 bytes: + - The seed value (16 bytes) + - A "root sequence" value (4 bytes), as a big-endian unsigned integer. Use 0 as a starting value for the root sequence. + + 2. Calculate the [SHA-512Half][] of the concatenated (seed+root sequence) value. + + 3. If the result is not a valid secp256k1 secret key, increment the root sequence by 1 and start over. [[Source]](https://github.com/XRPLF/rippled/blob/fc7ecd672a3b9748bfea52ce65996e324553c05f/src/ripple/crypto/impl/GenerateDeterministicKey.cpp#L103 "Source") + + A valid secp256k1 key must not be zero, and it must be numerically less than the _secp256k1 group order_. The secp256k1 group order is the constant value `0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141`. + + 4. With a valid secp256k1 secret key, use the standard ECDSA public key derivation with the secp256k1 curve to derive the root public key. (As always with cryptographic algorithms, use a standard, well-known, publicly-audited implementation whenever possible. For example, [OpenSSL](https://www.openssl.org/) has implementations of core Ed25519 and secp256k1 functions.) + + **Tip:** Validators use this root key pair. If you are calculating a validator's key pair, you can stop here. To distinguish between these two different types of public keys, the [base58][] serialization for validator public keys uses the prefix `0x1c`. + +2. Convert the root public key to its 33-byte compressed form. + + The uncompressed form of any ECDSA public key consists of a pair of 32-byte integers: an X coordinate, and a Y coordinate. The compressed form is the X coordinate and a one-byte prefix: `0x02` if the Y coordinate is even, or `0x03` if the Y coordinate is odd. + + You can convert an uncompressed public key to the compressed form with the `openssl` commandline tool. For example, if the uncompressed public key is in the file `ec-pub.pem`, you can output the compressed form like this: + + ``` + $ openssl ec -in ec-pub.pem -pubin -text -noout -conv_form compressed + ``` + +3. Derive an "intermediate key pair" from the compressed root public key you, as follows: + + 1. Concatenate the following in order, for a total of 41 bytes: + - The compressed root public key (33 bytes) + - `0x00000000000000000000000000000000` (4 bytes of zeroes). (This value was intended to be used to derive different members of the same family, but in practice only the value 0 is used.) + - A "key sequence" value (4 bytes), as a big-endian unsigned integer. Use 0 as a starting value for the key sequence. + + 2. Calculate the [SHA-512Half][] of the concatenated value. + + 3. If the result is not a valid secp256k1 secret key, increment the key sequence by 1 and restart deriving the account's intermediate key pair. + + 4. With a valid secp256k1 secret key, use the standard ECDSA public key derivation with the secp256k1 curve to derive the intermediate public key. (As always with cryptographic algorithms, use a standard, well-known, publicly-audited implementation whenever possible. For example, [OpenSSL](https://www.openssl.org/) has implementations of core Ed25519 and secp256k1 functions.) + +4. Derive the master public key pair by adding the intermediate public key to the root public key. Similarly, derive the secret key by adding the intermediate secret key to the root secret key. + + - An ECDSA secret key is a very large integer, so you can calculate the sum of two secret keys by summing them modulo the secp256k1 group order. + + - An ECDSA public key is a point on the elliptic curve, so you should use elliptic curve math to sum the points. + +5. Convert the master public key to its 33-byte compressed form, as before. + +6. When serializing an account's public key to its [base58][] format, use the account public key prefix, `0x23`. + + See [Address Encoding](addresses.md#address-encoding) for information and sample code to convert from an account's public key to its address. + + +## See Also + +- **Concepts:** + - [Issuing and Operational Addresses](account-types.md) +- **Tutorials:** + - [Assign a Regular Key Pair](../../tutorials/how-tos/manage-account-settings/assign-a-regular-key-pair.md) + - [Change or Remove a Regular Key Pair](../../tutorials/how-tos/manage-account-settings/change-or-remove-a-regular-key-pair.md) +- **References:** + - [SetRegularKey transaction][] + - [AccountRoot ledger object](../../references/protocol/ledger-data/ledger-entry-types/accountroot.md) + - [wallet_propose method][] + - [account_info method][] + +{% raw-partial file="/docs/_snippets/common-links.md" /%} From 3a6c14e1c957fef34572884989568a381fa8313c Mon Sep 17 00:00:00 2001 From: Amarantha Kulkarni Date: Wed, 17 Jul 2024 13:05:13 -0700 Subject: [PATCH 04/10] Create source file decentralized-identifiers.md --- decentralized-identifiers.md | 91 ++++++++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 decentralized-identifiers.md diff --git a/decentralized-identifiers.md b/decentralized-identifiers.md new file mode 100644 index 00000000000..881ab310914 --- /dev/null +++ b/decentralized-identifiers.md @@ -0,0 +1,91 @@ +--- +html: decentralized-identifiers.html +parent: accounts.html +seo: + description: Decentralized identifiers enable verifiable, decentralized digital identities. +status: not_enabled +labels: + - DID +--- +# Decentralized Identifiers + +_(Requires the [DID amendment][] {% not-enabled /%})_ + +A Decentralized Identifier (DID) is a new type of identifier defined by the World Wide Web Consortium (W3C) that enables verifiable, digital identities. DIDs are fully under the control of the DID owner, independent from any centralized registry, identity provider, or certificate authority. + +The key principles of a DID are: + +- **Decentralization:** No central issuing agency controls the DID, enabling the owner to update, resolve, or deactivate it. This also makes your identity highly-available, since DIDs are usually stored on a blockchain and always available for verification. + +- **Verifiable Credentials:** Anyone can create a DID and falsify the information on it. To prove the authenticity of a DID, a user must provide a verifiable credential (VC) that is cryptographically secure and tamper-evident. + + In the DID ecosystem, there are three parties: _user_, _issuer_, and _verifier_. The _user_ controls the DID, but needs a trusted _issuer_ to verify the information offline. The issuer provides a verfiable credential, which the user gives to _verifiers_ that need to confirm the user's identity. To learn more about the DID ecosystem, see: [Ecosystem Overview](https://www.w3.org/TR/vc-data-model/#ecosystem-overview). + +- **Interoperability:** DIDs are open to any solution that recognizes the W3C DID standard. This means a DID can be used to authenticate and establish trust in various digital transactions and interactions. + +**Note:** The implementation of DIDs on the XRP Ledger conforms to the requirements in the [DID v1.0 specification](https://www.w3.org/TR/did-core/). + + +## How It Works + +1. An XRPL account holder generates a DID that is controlled by the account. +2. The DID is associated with a DID document as defined by W3C specifications. +3. A user provides their DID and VC to a verifier for a digital task. +4. The verifier resolves the DID to its document and uses the VC to verify its authenticity. + + +## DID Documents + +DID documents contain the necessary information to cryptographically verify the identity of the subject described by a DID document. The subject can be a person, organization, or thing. For example, a DID document could contain cryptographic public keys that the DID subject can use to authenticate itself and prove its association with the DID. + +**Note:** DID documents usually serialize to a JSON or JSON-LD representation. + +On the XRP Ledger, there are several ways to associate a DID to a DID document: + +1. Store a reference to the document in the `URI` field of the `DID` object, which points to a document stored on another decentralized storage network, such as IPFS or STORJ. +2. Store a minimal DID document in the `DIDDocument` field of the `DID` object. +3. Use a minimal _implicit_ DID document generated from the DID and other available public information. + **Note:** Simpler use cases may only need signatures and simple authorization tokens. In cases where there isn't explicitly a DID document on the ledger, an implicit document is used instead. For example, the implicit DID Document of `did:xrpl:1:0330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD020` enables only a single key `0330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD020` to authorize changes on the DID document or sign credentials in the name of the DID. + + +### Sample XRPL DID Document + +```json +{ + "@context": "https://w3id.org/did/v1", + "id": "did:xrpl:1:rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", + "publicKey": [ + { + "id": "did:xrpl:1:rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn#keys-1", + "type": ["CryptographicKey", "EcdsaKoblitzPublicKey"], + "curve": "secp256k1", + "expires": 15674657, + "publicKeyHex": "04f42987b7faee8b95e2c3a3345224f00e00dfc67ba882..." + } + ] +} +``` + +To learn more about the core properties of a DID document, see: [Decentralized Identifiers (DIDs) v1.0](https://www.w3.org/TR/did-core/#core-properties). + + +## Privacy and Security Concerns + +- Whoever controls the private keys of an XRPL account, controls the DID and reference to the DID document it resolves to. Take care to ensure your private keys aren't compromised. +- You can include any content in a DID document, but should limit it to verification methods and service points. Since DIDs on XRPL are publicly available, you shouldn't include any personal information. +- IPFS allows anyone to store content on the nodes in a distributed network. A common misconception is that anyone can edit that content; however, the content-addressability of IPFS means any edited content will have a different address from the original. While any entity can copy a DID document anchored with an XRPL account's `DIDDocument` or `URI` fields, they can't change the document itself unless they control the private key that created the corresponding `DID` object. + + +## Use Cases + +DIDs enable many use cases, such as: + +- Meeting Know Your Client (KYC) and Anti-money Laundering (AML) standards. +- User identity management across the XRP Ledger. +- Differentiated access to DeFi apps. +- Signing digital documents. +- Making secure online transactions. +- Logging into websites. + + +{% raw-partial file="/docs/_snippets/common-links.md" /%} From 254273aa363e52cff19daedb551b74e6e710efbd Mon Sep 17 00:00:00 2001 From: Amarantha Kulkarni Date: Wed, 17 Jul 2024 13:05:14 -0700 Subject: [PATCH 05/10] Create source file deleting-accounts.md --- deleting-accounts.md | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 deleting-accounts.md diff --git a/deleting-accounts.md b/deleting-accounts.md new file mode 100644 index 00000000000..28c2f8c0661 --- /dev/null +++ b/deleting-accounts.md @@ -0,0 +1,38 @@ +--- +html: deleting-accounts.html +parent: accounts.html +seo: + description: About deleting an XRP Ledger account. +labels: + - Accounts +--- +# Deleting Accounts + +The owner of an account can send an [AccountDelete transaction][] to deletes the account and related entries from the ledger, sending most of the account's remaining XRP balance to another account. To discourage wasteful creation and deletion of accounts, deleting an account requires burning a higher than usual amount of XRP as the [transaction cost](../transactions/transaction-cost.md). + +Some types of associated ledger entries block an account from being deleted. For example, the issuer of a fungible token can't be deleted while anyone holds a nonzero balance of that token. + +After an account has been deleted, it can be re-created in the ledger through the normal method of [creating accounts](index.md#creating-accounts). An account that has been deleted and re-created is no different than an account that has been created for the first time. + +## Requirements + +To be deleted, an account must meet the following requirements: + +- The account's `Sequence` number plus 256 must be less than the current [Ledger Index][]. +- The account must not be linked to any of the following types of [ledger entries](../../references/protocol/ledger-data/ledger-entry-types/index.md) (as a sender or receiver): + - `Escrow` + - `PayChannel` + - `RippleState` + - `Check` +- The account must own fewer than 1000 objects in the ledger. +- The transaction must pay a special [transaction cost][] equal to at least the [owner reserve](reserves.md) for one item (currently 2 XRP). + +## Cost of Deleting + +**Warning:** The [AccountDelete transaction][]'s transaction cost always applies when the transaction is included in a validated ledger, even if the transaction failed because the account does not meet the requirements to be deleted. To greatly reduce the chances of paying the high transaction cost if the account cannot be deleted, use the `fail_hard` option when submitting an AccountDelete transaction. + +Unlike Bitcoin and many other cryptocurrencies, each new version of the XRP Ledger's public ledger chain contains the full state of the ledger, which increases in size with each new account. For that reason, you should not create new XRP Ledger accounts unless necessary. You can recover some of an account's 10 XRP [reserve](reserves.md) by deleting the account, but you must still destroy at least 2 XRP to do so. + +Institutions who send and receive value on behalf of many users can use [**Source Tags** and **Destination Tags**](../transactions/source-and-destination-tags.md) to distinguish payments from and to their customers while only using one (or a handful) of accounts in the XRP Ledger. + +{% raw-partial file="/docs/_snippets/common-links.md" /%} From 3b1e7fef584f5077cf28cdc88aed6d05ab32538d Mon Sep 17 00:00:00 2001 From: Amarantha Kulkarni Date: Wed, 17 Jul 2024 13:05:14 -0700 Subject: [PATCH 06/10] Create source file depositauth.md --- depositauth.md | 119 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 119 insertions(+) create mode 100644 depositauth.md diff --git a/depositauth.md b/depositauth.md new file mode 100644 index 00000000000..b097e96b6ff --- /dev/null +++ b/depositauth.md @@ -0,0 +1,119 @@ +--- +html: depositauth.html +parent: accounts.html +seo: + description: The DepositAuth setting lets an account block incoming payments by default. +labels: + - Payments + - Security +--- +# Deposit Authorization + +_(Added by the [DepositAuth amendment][].)_ + +Deposit Authorization is an optional [account](index.md) setting in the XRP Ledger. If enabled, Deposit Authorization blocks all transfers from strangers, including transfers of XRP and [tokens](../tokens/index.md). An account with Deposit Authorization can only receive value in two ways: + +- From accounts it has [preauthorized](#preauthorization). +- By sending a transaction to receive the funds. For example, an account with Deposit Authorization could finish an [Escrow](../payment-types/escrow.md) that was initiated by a stranger. + +By default, new accounts have DepositAuth disabled and can receive XRP from anyone. + +## Background + +Financial services regulations and licenses may require that a business or entity must know the sender of all transactions it receives. This presents a challenge on a decentralized system like the XRP Ledger where participants are identified by pseudonyms which can be freely generated and the default behavior is for any address to be able to pay any other. + +The Deposit Authorization flag introduces an option for those using the XRP Ledger to comply with such regulations without changing the fundamental nature of the decentralized ledger. With Deposit Authorization enabled, an account can only receive funds it explicitly approves by sending a transaction. The owner of an account using Deposit Authorization can perform the due diligence necessary to identify the sender of any funds _before_ sending the transaction that causes the account to receive the money. + +When you have Deposit Authorization enabled, you can receive money from [Checks](/resources/known-amendments.md#checks), [Escrow](../payment-types/escrow.md), and [Payment Channels](/resources/known-amendments.md#paychan). In these transactions' "two-step" model, first the source sends a transaction to authorize sending funds, then the destination sends a transaction to authorize receiving those funds. + +To receive money from [Payment transactions][] when you have Deposit Authorization enabled, you must [preauthorize](#preauthorization) the senders of those Payments. _(Added by the [DepositPreauth amendment][].)_ + +## Recommended Usage + +To get the full effect of Deposit Authorization, Ripple recommends also doing the following: + +- Always maintain an XRP balance higher than the minimum [reserve requirement](reserves.md). +- Keep the Default Ripple flag in its default (disabled) state. Do not enable [rippling](../tokens/fungible-tokens/rippling.md) on any trust lines. When sending [TrustSet transactions][], always use the [`tfSetNoRipple` flag](../../references/protocol/transactions/types/trustset.md). +- Do not place [Offers](../../references/protocol/transactions/types/offercreate.md). It is impossible to know in advance which matching offers will be consumed to execute such a trade. + +## Precise Semantics + +An account with Deposit Authorization enabled: + +- **Cannot** be the destination of [Payment transactions][], with **the following exceptions**: + - If the destination has [preauthorized](#preauthorization) the sender of the Payment. _(Added by the [DepositPreauth amendment][])_ + - If the account's XRP balance is equal to or below the minimum account [reserve requirement](reserves.md), it can be the destination of an XRP Payment whose `Amount` is equal or less than the minimum account reserve (currently 10 XRP). This is to prevent an account from becoming "stuck" by being unable to send transactions but also unable to receive XRP. The account's owner reserve does not matter for this case. +- Can receive XRP from [PaymentChannelClaim transactions][] **only in the following cases**: + - The sender of the PaymentChannelClaim transaction is the destination of the payment channel. + - The destination of the PaymentChannelClaim transaction has [preauthorized](#preauthorization) the sender of the PaymentChannelClaim. _(Added by the [DepositPreauth amendment][])_ +- Can receive XRP from [EscrowFinish transactions][] **only in the following cases**: + - The sender of the EscrowFinish transaction is the destination of the escrow. + - The destination of the EscrowFinish transaction has [preauthorized](#preauthorization) the sender of the EscrowFinish. _(Added by the [DepositPreauth amendment][])_ +- **Can** receive XRP or tokens by sending a [CheckCash][] transaction. _(Added by the [Checks amendment][].)_ +- **Can** receive XRP or tokens by sending [OfferCreate transactions][]. + - If the account sends an OfferCreate transaction that is not fully executed immediately, it **can** receive the rest of the ordered XRP or token later when the offer is consumed by other accounts' [Payment][] and [OfferCreate][] transactions. +- If the account has created any trust lines without the [No Ripple flag](../tokens/fungible-tokens/rippling.md) enabled, or has enabled the Default Ripple flag and issued any currency, the account **can** receive the tokens of those trust lines in [Payment transactions][] as a result of rippling. It cannot be the destination of those transactions. +- In general, an account in the XRP Ledger **cannot** receive any non-XRP currencies in the XRP Ledger as long as all of the following are true. (This rule is not specific to the DepositAuth flag.) + - The account has not created any trust lines with a nonzero limit. + - The account has not issued tokens on trust lines created by others. + - The account has not placed any offers. + +The following table summarizes whether a transaction type can deposit money with DepositAuth enabled or disabled: + +{% partial file="/docs/_snippets/depositauth-semantics-table.md" /%} + + + +## Enabling or Disabling Deposit Authorization + +An account can enable deposit authorization by sending an [AccountSet transaction][] with the `SetFlag` field set to the `asfDepositAuth` value (9). The account can disable deposit authorization by sending an [AccountSet transaction][] with the `ClearFlag` field set to the `asfDepositAuth` value (9). For more information on AccountSet flags, see [AccountSet flags](../../references/protocol/transactions/types/accountset.md). + +## Checking Whether an Account Has DepositAuth Enabled + +To see whether an account has Deposit Authorization enabled, use the [account_info method][] to look up the account. Compare the value of the `Flags` field (in the `result.account_data` object) with the [bitwise flags defined for an AccountRoot ledger object](../../references/protocol/ledger-data/ledger-entry-types/accountroot.md). + +If the result of the `Flags` value bitwise-AND the `lsfDepositAuth` flag value (`0x01000000`) is nonzero, then the account has DepositAuth enabled. If the result is zero, then the account has DepositAuth disabled. + +## Preauthorization + +_(Added by the [DepositPreauth amendment][].)_ + +Accounts with DepositAuth enabled can _preauthorize_ certain senders, to allow payments from those senders to succeed even with DepositAuth enabled. This allows specific senders to send funds directly without the receiver taking action on each transaction individually. Preauthorization is not required to use DepositAuth, but can make certain operations more convenient. + +Preauthorization is currency-agnostic. You cannot preauthorize accounts for specific currencies only. + +To preauthorize a particular sender, send a [DepositPreauth transaction][] with the address of another account to preauthorize in the `Authorize` field. To revoke preauthorization, provide the other account's address in the `Unauthorize` field instead. Specify your own address in the `Account` field as usual. You can preauthorize or unauthorize accounts even if you do not currently have DepositAuth enabled; the preauthorization status you set for other accounts is saved, but has no effect unless you enable DepositAuth. An account cannot preauthorize itself. Preauthorizations are one-directional, and have no effect on payments going the opposite direction. + +Preauthorizing another account adds a [DepositPreauth object](../../references/protocol/ledger-data/ledger-entry-types/depositpreauth.md) to the ledger, which increases the [owner reserve](reserves.md#owner-reserves) of the account providing the authorization. If the account revokes this preauthorization, doing so removes the object and decreases the owner reserve. + +After the DepositPreauth transaction has been processed, the authorized account can send funds to your account, even if you have DepositAuth enabled, using any of the following transaction types: + +- [Payment][] +- [EscrowFinish][] +- [PaymentChannelClaim][] + +Preauthorization has no effect on the other ways to send money to an account with DepositAuth enabled. See [Precise Semantics](#precise-semantics) for the exact rules. + +### Checking for Authorization + +You can use the [deposit_authorized method][] to see if an account is authorized to deposit to another account. This method checks two things: + +- Whether the destination account requires Deposit Authorization. (If it does not require authorization, then all source accounts are considered authorized.) +- Whether the source account is preauthorized to send money to the destination. + + +## See Also + +- The [DepositPreauth transaction][] reference. +- The [DepositPreauth ledger object type](../../references/protocol/ledger-data/ledger-entry-types/depositpreauth.md). +- The [deposit_authorized method][] of the [`rippled` API](../../references/http-websocket-apis/index.md). +- The [Authorized Trust Lines](../tokens/fungible-tokens/authorized-trust-lines.md) feature (`RequireAuth` flag) limits which counterparties can hold non-XRP currencies issued by an account. +- The `DisallowXRP` flag indicates that an account should not receive XRP. This is a softer protection than Deposit Authorization, and is not enforced by the XRP Ledger. (Client applications should honor this flag or at least warn about it.) +- The `RequireDest` flag indicates that an account can only receive currency amounts if the sending transaction specifies a [Destination Tag](../transactions/source-and-destination-tags.md). This protects users from forgetting to indicate the purpose of a payment, but does not protect recipients from unknown senders, who can make up arbitrary destination tags. +- [Partial Payments](../payment-types/partial-payments.md) provide a way for accounts to return unwanted payments while subtracting [transfer fees](../tokens/transfer-fees.md) and exchange rates from the amount delivered instead of adding them to the amount sent. + + + +[DepositPreauth amendment]: /resources/known-amendments.md#depositpreauth + +{% raw-partial file="/docs/_snippets/common-links.md" /%} From 15e224e631dda480036ab4db6572d52ddc0bf469 Mon Sep 17 00:00:00 2001 From: Amarantha Kulkarni Date: Wed, 17 Jul 2024 13:05:15 -0700 Subject: [PATCH 07/10] Create source file index.md --- index.md | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 index.md diff --git a/index.md b/index.md new file mode 100644 index 00000000000..5371eaa1c4b --- /dev/null +++ b/index.md @@ -0,0 +1,69 @@ +--- +html: accounts.html +parent: concepts.html +seo: + description: Learn about accounts in the XRP Ledger. Accounts can send transactions and hold XRP. +labels: + - Accounts + - Payments +--- +# Accounts + +An "Account" in the XRP Ledger represents a holder of XRP and a sender of [transactions](../../references/protocol/transactions/index.md). + +An account consists of an address, an XRP balance, a sequence number, and a history of its transactions. To be able to send transactions, the owner also needs one or more cryptographic key pairs associated with the account. + + +## Account Structure + + The core elements of an account are: + +- An identifying **address**, such as `rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn`. +- An **XRP balance**. Some of this XRP is set aside for the [Reserve](reserves.md). +- A **sequence number**, which helps make sure any transactions this account sends are applied in the correct order and only once. To execute a transaction, the transaction's sequence number and its sender's sequence number must match. Then, as part of applying the transaction, the account's sequence number increases by 1. (See also: [Basic Data Types: Account Sequence](../../references/protocol/data-types/basic-data-types.md#account-sequence).) +- A **history of transactions** that affected this account and its balances. +- One or more ways to [authorize transactions](../transactions/index.md#authorizing-transactions), possibly including: + - A master key pair intrinsic to the account. (This can be disabled but not changed.) + - A "regular" key pair that can be rotated. + - A signer list for [multi-signing](multi-signing.md). (Stored separately from the account's core data.) + +An account's core data is stored in an [AccountRoot](../../references/protocol/ledger-data/ledger-entry-types/accountroot.md) ledger entry. An account can also be the owner (or partial owner) of several other types of ledger entry. + +**Tip:** An "Account" in the XRP Ledger is somewhere between the financial usage (like "bank account") and the computing usage (like "UNIX account"). Non-XRP currencies and assets aren't stored in an XRP Ledger Account itself; each such asset is stored in an accounting relationship called a "Trust Line" that connects two parties. + + +## Creating Accounts + +There is not a dedicated "create account" transaction. The [Payment transaction][] automatically creates a new account if the payment sends enough XRP to a mathematically-valid address that does not already have an account. This is called _funding_ an account, and creates an [AccountRoot entry](../../references/protocol/ledger-data/ledger-entry-types/accountroot.md) in the ledger. No other transaction can create an account. + +**Caution:** Funding an account **does not** give you any special privileges over that account. Whoever has the secret key corresponding to the account's address has full control over the account and all XRP it contains. For some addresses, it's possible that no one has the secret key, in which case the account is a [black hole](addresses.md#special-addresses) and the XRP is lost forever. + +The typical way to get an account in the XRP Ledger is as follows: + +1. Generate a key pair from a strong source of randomness and calculate the address of that key pair. + +2. Have someone who already has an account in the XRP Ledger send XRP to the address you generated. + + - For example, you can buy XRP in a private exchange, then withdraw XRP from the exchange to the address you specified. + + **Caution:** The first time you receive XRP at your own XRP Ledger address, you must pay the [account reserve](reserves.md) (currently 10 XRP), which locks up that amount of XRP indefinitely. In contrast, private exchanges usually hold all their customers' XRP in a few shared XRP Ledger accounts, so customers don't have to pay the reserve for individual accounts at the exchange. Before withdrawing, consider whether having your own account directly on the XRP Ledger is worth the price. + + + +## See Also + +- **Concepts:** + - [Reserves](reserves.md) + - [Cryptographic Keys](cryptographic-keys.md) + - [Issuing and Operational Addresses](account-types.md) +- **References:** + - [account_info method][] + - [wallet_propose method][] + - [AccountSet transaction][] + - [Payment transaction][] + - [AccountRoot object](../../references/protocol/ledger-data/ledger-entry-types/accountroot.md) +- **Tutorials:** + - [Manage Account Settings (Category)](../../tutorials/how-tos/manage-account-settings/index.md) + - [Monitor Incoming Payments with WebSocket](../../tutorials/http-websocket-apis/build-apps/monitor-incoming-payments-with-websocket.md) + +{% raw-partial file="/docs/_snippets/common-links.md" /%} From 074263f2a20cc3eb1a91845f7bf4c580180bccaf Mon Sep 17 00:00:00 2001 From: Amarantha Kulkarni Date: Wed, 17 Jul 2024 13:05:16 -0700 Subject: [PATCH 08/10] Create source file multi-signing.md --- multi-signing.md | 86 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 multi-signing.md diff --git a/multi-signing.md b/multi-signing.md new file mode 100644 index 00000000000..a4f9f4504bc --- /dev/null +++ b/multi-signing.md @@ -0,0 +1,86 @@ +--- +html: multi-signing.html +parent: accounts.html +seo: + description: Use multi-signing for greater security sending transactions. +labels: + - Smart Contracts + - Security +--- +# Multi-Signing + +Multi-signing in the XRP Ledger is a method of [authorizing transactions](../transactions/index.md#authorizing-transactions) for the XRP Ledger by using a combination of multiple secret keys. You can have any combination of authorization methods enabled for your address, including multi-signing, a [master key pair](cryptographic-keys.md#master-key-pair), and a [regular key pair](cryptographic-keys.md#regular-key-pair). (The only requirement is that _at least one_ method must be enabled.) + +Benefits of multi-signing include: + +- You can require keys from different devices, so that a malicious actor must compromise multiple machines to send transactions on your behalf. +- You can share custody of an address between multiple people, each of whom only has one of several keys necessary to send transactions from that address. +- You can delegate the power to send transactions from your address to a group of people, who can control your address if you are unavailable or unable to sign normally. + +## Signer Lists + +Before you can multi-sign, you must create a list of which addresses can sign for you. + +The [SignerListSet transaction][] defines a _signer list_, a set of addresses that can authorize transactions from your address. You can include 1 to 32 addresses in a signer list. The list cannot include your address and there can be no duplicate entries. You can control how many signatures are needed, in which combinations, by using the _Signer Weight_ and _Quorum_ settings in the list. + +_(Updated by the [ExpandedSignerList amendment][].)_ + +### Signer Weight + +You assign a weight to each signer in the list. The weight represents the authority of the signer relative to other signers on the list. The higher the value, the more authority. Individual weight values cannot exceed 216-1. + +### Quorum + +The quorum value of a list is the minimum weight total required to authorize a transaction. The quorum must be greater than 0 but less than or equal to the sum of the weight values in the signer list: meaning, it must be possible to achieve a quorum with the given signer weights. + +### Wallet Locator + + +You can also add up to 256 bits of arbitrary data to each signer's entry in the list. This data is not required or used by the network, but can be used by smart contracts or other applications to identify or confirm other data about the signers. + +_(Added by the [ExpandedSignerList amendment][].)_ + + +### Examples Using Signer Weight and Quorum + +The weights and quorum allow you to set an appropriate level of oversight for each transaction, based on the relative trust and authority relegated to responsible participants who manage the account. + +For a shared account use case, you might create a list with a quorum of 1, then give all participants a weight of 1. A single approval from any one of them is all that is required to approve a transaction. + +For a very important account, you might set the quorum to 3, with 3 participants that have a weight of 1. All of the participants must agree and approve each transaction. + +Another account might also have a quorum of 3. You assign your CEO a weight of 3, 3 Vice Presidents a weight of 2 each, and 3 Directors a weight of 1 each. To approve a transaction for this account requires the approval of all 3 Directors (total weight of 3), 1 Vice President and 1 Director (total weight of 3), 2 Vice Presidents (total weight of 4), or the CEO (total weight of 3). + +In each of the previous three use cases, you would disable the master key without configuring a regular key, so that multi-signing is the only way of [authorizing transactions](../transactions/index.md#authorizing-transactions). + +There might be a scenario where you create a multi-signing list as a "backup plan." The account owner normally uses a regular key for their transactions (not a multi-signing key). For safety, the owner adds a signer list containing 3 friends, each with a weight of 1, and a quorum of 3. If the account owner were to lose the private key, they can ask their friends to multi-sign a transaction to replace the regular key. + + +## Sending Multi-Signed Transactions + +To successfully submit a multi-signed transaction, you must do all of the following: + +* The address sending the transaction (specified in the `Account` field) must have a [`SignerList` object in the ledger](../../references/protocol/ledger-data/ledger-entry-types/signerlist.md). For instructions on how to do this, see [Set Up Multi-Signing](../../tutorials/how-tos/manage-account-settings/set-up-multi-signing.md). +* The transaction must include the `SigningPubKey` field as an empty string. +* The transaction must include a [`Signers` field](../../references/protocol/transactions/common-fields.md#signers-field) containing an array of signatures. +* The signatures present in the `Signers` array must match signers defined in the `SignerList`. +* For the provided signatures, the total weight associated with those signers must be equal or greater than the quorum for the `SignerList`. +* The [transaction cost](../transactions/transaction-cost.md) (specified in the `Fee` field) must be at least (N+1) times the normal transaction cost, where N is the number of signatures provided. +* All fields of the transaction must be defined before collecting signatures. You cannot [auto-fill](../../references/protocol/transactions/common-fields.md#auto-fillable-fields) any fields. +* If presented in binary form, the `Signers` array must be sorted based on the numeric value of the signer addresses, with the lowest value first. (If submitted as JSON, the [submit_multisigned method][] handles this automatically.) + +## See Also + +- **Tutorials:** + - [Set Up Multi-Signing](../../tutorials/how-tos/manage-account-settings/set-up-multi-signing.md) + - [Send a Multi-Signed Transaction](../../tutorials/how-tos/manage-account-settings/send-a-multi-signed-transaction.md) +- **Concepts:** + - [Cryptographic Keys](cryptographic-keys.md) + - [Special Transaction Cost for Multi-signed transactions](../transactions/transaction-cost.md#special-transaction-costs) +- **References:** + - [SignerListSet transaction][] + - [SignerList object](../../references/protocol/ledger-data/ledger-entry-types/signerlist.md) + - [sign_for method][] + - [submit_multisigned method][] + +{% raw-partial file="/docs/_snippets/common-links.md" /%} From 85df42bac6f80d343db23cf3eade604e37d06187 Mon Sep 17 00:00:00 2001 From: Amarantha Kulkarni Date: Wed, 17 Jul 2024 13:05:16 -0700 Subject: [PATCH 09/10] Create source file reserves.md --- reserves.md | 85 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 reserves.md diff --git a/reserves.md b/reserves.md new file mode 100644 index 00000000000..f967f1170a5 --- /dev/null +++ b/reserves.md @@ -0,0 +1,85 @@ +--- +html: reserves.html +parent: accounts.html +seo: + description: XRP Ledger accounts require a reserve of XRP to reduce spam in ledger data. +labels: + - Fees + - Accounts +top_nav_grouping: Popular Pages +--- +# Reserves + +The XRP Ledger applies _reserve requirements_, in XRP, to protect the shared global ledger from growing excessively large as the result of spam or malicious usage. The goal is to constrain the growth of the ledger to match improvements in technology so that a current commodity-level machine can always fit the current ledger in RAM. + +To have an account, an address must hold a minimum amount of XRP in the shared global ledger. To fund a new address, you must receive enough XRP at that address to meet the reserve requirement. You cannot send the reserved XRP to others, but you can recover some of the XRP by [deleting the account](deleting-accounts.md). + +The XRP reserve is not dormant, however. You can use your reserves to pay transaction fees. Another way to look at your reserves is that you are pre-funding your account to handle your transaction fees. + +The reserve requirement changes from time to time due to the [Fee Voting](../consensus-protocol/fee-voting.md) process, where validators can agree to new reserve settings. + +## Base Reserve and Owner Reserve + +The reserve requirement has two parts: + +* The **Base Reserve** is a minimum amount of XRP that is required for each address in the ledger. +* The **Owner Reserve** is an increase to the reserve requirement for each object that the address owns in the ledger. The cost per item is also called the _incremental reserve_. + +The current reserve requirements on Mainnet are: + +- Base reserve: **10 XRP** +- Owner reserve: **2 XRP** per item + +Reserves on other networks may vary. + +An exception to the owner reserve is that you can create your first two trust lines on the XRPL without the required reserves of 2 XRP per trust line. Create your new account with the 10 XRP base reserve, then create your 2 trust lines and the reserves are not required. If you fund your account with more than 10 XRP, your account will be charged the normal reserve fees for your first two trust lines. + +## Owner Reserves + +Many objects in the ledger (ledger entries) are owned by a particular account. Usually, the owner is the account that created the object. Each object increases the owner's total reserve requirement by the owner reserve. When objects are removed from the ledger, they no longer count against the reserve requirement. + +Objects that count towards their owner's reserve requirement include: [Checks](../payment-types/checks.md), [Deposit Preauthorizations](depositauth.md#preauthorization), [Escrows](../payment-types/escrow.md), [NFT Offers](../tokens/nfts/trading.md), [NFT Pages](../tokens/nfts/index.md), [Offers](../../references/protocol/ledger-data/ledger-entry-types/offer.md), [Payment Channels](../payment-types/payment-channels.md), [Signer Lists](multi-signing.md), [Tickets](tickets.md), and [Trust Lines](../tokens/fungible-tokens/index.md). + +Some special cases: + +- Non-Fungible Tokens (NFTs) are grouped into pages containing up to 32 NFTs each, and the owner reserve applies per page rather than per NFT. Due to the mechanism for splitting and combining pages, the number of NFTs actually stored per page varies. See also: [Reserve for NFTokenPage objects](../../references/protocol/ledger-data/ledger-entry-types/nftokenpage.md#nftokenpage-reserve). +- Trust lines (`RippleState` entries) are shared between two accounts. The owner reserve can apply to one or both of them. Most often, the token holder owes a reserve and the issuer does not. See also: [RippleState: Contributing to the Owner Reserve](../../references/protocol/ledger-data/ledger-entry-types/ripplestate.md#contributing-to-the-owner-reserve). +- Signer lists created before the [MultiSignReserve amendment][] activated in April 2019 count as multiple objects. See also: [Signer Lists and Reserves](../../references/protocol/ledger-data/ledger-entry-types/signerlist.md#signer-lists-and-reserves). +- An [Owner Directory](../../references/protocol/ledger-data/ledger-entry-types/directorynode.md) is a ledger entry that lists all objects related to an account, including all objects the account owns. However, the owner directory itself does not count towards the reserve. + +### Looking Up Reserves + +Applications can look up the current base and incremental reserve values using the [server_info method][] or [server_state method][]: + +| Method | Units | Base Reserve Field | Incremental Reserve Field | +|-------------------------|----------------------|-------------------------------------|------------------------------------| +| [server_info method][] | Decimal XRP | `validated_ledger.reserve_base_xrp` | `validated_ledger.reserve_inc_xrp` | +| [server_state method][] | Integer drops of XRP | `validated_ledger.reserve_base` | `validated_ledger.reserve_inc` | + +To determine the owner reserve of an account, multiply the incremental reserve by the number of objects the account owns. To look up the number of objects an account owns, call the [account_info method][] and take `account_data.OwnerCount`. + +To calculate an address's total reserve requirement, multiply `OwnerCount` by `reserve_inc_xrp`, then add `reserve_base_xrp`. [Here is a demonstration](../../tutorials/python/build-apps/build-a-desktop-wallet-in-python.md#codeblock-17) of this calculation in Python. + + +## Going Below the Reserve Requirement + +During transaction processing, the [transaction cost](../transactions/transaction-cost.md) destroys some of the sending address's XRP balance. This can cause an address's XRP to go below the reserve requirement. You can even destroy _all_ of your XRP this way. + +When your account holds less XRP than its current reserve requirement, you cannot send XRP to others, or create new objects that would increase your account's reserve requirement. Even so, the account continues to exist in the ledger and you can still send transactions that don't do these things, as long as you have enough XRP to pay the transaction cost. You can go back above the reserve requirement by receiving enough XRP, or if the reserve requirement decreases below the amount you have. + +**Tip:** If your address is below the reserve requirement, you can send an [OfferCreate transactions][] to acquire more XRP and get back above the reserve requirement. However, since you cannot create an [Offer entry in the ledger](../../references/protocol/ledger-data/ledger-entry-types/offer.md) while you are below the reserve, this transaction can only consume Offers that are already in the order books. + + +## Changing the Reserve Requirements + +The XRP Ledger has a mechanism to adjust the reserve requirements. Such adjustments may consider, for example, long-term changes in the value of XRP, improvements in the capacity of commodity-level machine hardware, or increased efficiency in the server software implementation. Any changes have to be approved by the consensus process. See [Fee Voting](../consensus-protocol/fee-voting.md) for more information. + +## See Also + +- [account_objects method][] +- [AccountRoot Object][] +- [Fee Voting](../consensus-protocol/fee-voting.md) +- [SetFee pseudo-transaction][] +- [Tutorial: Calculate and display the reserve requirement (Python)](../../tutorials/python/build-apps/build-a-desktop-wallet-in-python.md#3-display-an-account) + +{% raw-partial file="/docs/_snippets/common-links.md" /%} From c0b39151aafb3ed9726f6999b0d68e1f2ed20aa0 Mon Sep 17 00:00:00 2001 From: Amarantha Kulkarni Date: Wed, 17 Jul 2024 13:05:17 -0700 Subject: [PATCH 10/10] Create source file tickets.md --- tickets.md | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 tickets.md diff --git a/tickets.md b/tickets.md new file mode 100644 index 00000000000..9e28a8d45e9 --- /dev/null +++ b/tickets.md @@ -0,0 +1,73 @@ +--- +html: tickets.html +parent: accounts.html +seo: + description: Send transactions in non-sequential order. +labels: + - Accounts + - Transaction Sending +--- +# Tickets + +_(Added by the [TicketBatch amendment][].)_ + +A Ticket in the XRP Ledger is a way of setting aside a [sequence number][Sequence Number] for a transaction without sending it right away. Tickets allow transactions to be sent outside of the normal sequence order. One use case for this is to allow for [multi-signed transactions](multi-signing.md) where it may take a while to collect the necessary signatures: while collecting signatures for a transaction that uses a Ticket, you can still send other transactions. + +## Background + +[Transactions](../transactions/index.md) have sequence numbers so that any given transaction can execute no more than once. Sequence numbers also make sure any given transaction is unique: if you send the exact same amount of money to the same person multiple times, the Sequence Number is one detail that is guaranteed to be different each time. Finally, Sequence Numbers provide an elegant way to put transactions in a consistent order, even if some of them arrive out of order when sent throughout the network. + +However, there are some situations where sequence numbers are too limiting. For example: + +- Two or more users share access to an account, each with the ability to send transactions independently. If these users try to send transactions around the same time without coordinating first, they may each try to use the same Sequence number for different transactions, and only one can succeed. +- You may want to prepare and sign a transaction in advance, then save it in some secure storage so that it can be executed at any future point if certain events occur. However, if you want to continue using your account as normal in the meantime, you don't know what Sequence number the set-aside transaction will need. +- When [multiple people must sign a transaction](multi-signing.md) to make it valid, it can be difficult to plan more than one transaction at a time. If you number the transactions with separate sequence numbers, you can't send the later-numbered transactions until everyone has signed the previous transactions; but if you use the same sequence number for each pending transactions, only one of them can succeed. + +Tickets provide a solution to all of these problems by setting aside sequence numbers that can be used later, outside of their usual order, but still no more than once each. + + +## Tickets Are Reserved Sequence Numbers + +A Ticket is a record that a sequence number has been set aside to be used later. An account first sends a [TicketCreate transaction][] to set aside one or more sequence numbers as Tickets; this puts a record in the [ledger's state data](../ledgers/index.md), in the form of a [Ticket object][], for each sequence number reserved. + +Tickets are numbered using the sequence numbers that were set aside to create them. For example, if your account's current sequence number is 101 and you create 3 Tickets, those Tickets have Ticket Sequence numbers 102, 103, and 104. Doing so increases your account's sequence number to 105. + +[{% inline-svg file="/docs/img/ticket-creation.svg" /%}](/docs/img/ticket-creation.svg "Diagram: Creating three Tickets") + +Later, you can send a transaction using a specific Ticket instead of a sequence number; doing so removes the corresponding Ticket from the ledger's state data and does not change your account's normal sequence number. You can also still send transactions using normal sequence numbers without using Tickets. You can use any of your available Tickets in any order at any time, but each Ticket can only be used once. + +[{% inline-svg file="/docs/img/ticket-usage.svg" /%}](/docs/img/ticket-usage.svg "Diagram: Using Ticket 103.") + +Continuing the above example, you can send a transaction using sequence number 105 or any of the three Tickets you created. If you send a transaction using Ticket 103, doing so deletes Ticket 103 from the ledger. Your next transaction after that can use sequence number 105, Ticket 102, or Ticket 104. + +**Caution:** Each Ticket counts as a separate item for the [owner reserve](reserves.md), so you must set aside 2 XRP for each Ticket. (The XRP becomes available again after you use the Ticket.) This cost can add up quickly if you create a large number of Tickets at once. + +As with sequence numbers, sending a transaction uses up the Ticket _if and only if_ the transaction is confirmed by [consensus](../consensus-protocol/index.md). However, transactions that fail to do what they were intended to do can still be confirmed by consensus with [`tec`-class result codes](../../references/protocol/transactions/transaction-results/tec-codes.md). + +To look up what Tickets an account has available, use the [account_objects method][]. + +## Limitations + +Any account can create and use Tickets on any type of transaction. However, some restrictions apply: + +- Each Ticket can only be used once. It is possible to have multiple different candidate transactions that would use the same Ticket Sequence, but only one of those candidates can be validated by consensus. +- Each account cannot have more than 250 Tickets in the ledger at a time. You cannot create more than 250 Tickets at a time, either. +- You _can_ use a Ticket to create more Tickets. If you do, the Ticket you used does not count towards the total number of Tickets you can have at once. +- Each Ticket counts toward the [owner reserve](reserves.md), so you must set aside 2 XRP for each Ticket you have not used yet. The XRP becomes available for you to use again after the Ticket is used. +- Within an individual ledger, transactions that use Tickets execute after other transactions from the same sender. If an account has multiple transactions using Tickets in the same ledger version, those Tickets execute in order from lowest Ticket Sequence to highest. (For more information, see the documentation on consensus's [canonical order](../consensus-protocol/consensus-structure.md#calculate-and-share-validations).) +- To "cancel" a Ticket, use the Ticket to [perform a no-op](../transactions/finality-of-results/canceling-a-transaction.md) [AccountSet transaction][]. This deletes the Ticket so that you don't have to meet its reserve requirement. + +## See Also + + +- **Concepts:** + - [Multi-Signing](multi-signing.md) +- **Tutorials:** + - [Use Tickets](../../tutorials/how-tos/manage-account-settings/use-tickets.md) +- **References:** + - [TicketCreate transaction][] + - [Transaction Common Fields](../../references/protocol/transactions/common-fields.md) + - [Ticket object](../../references/protocol/ledger-data/ledger-entry-types/ticket.md) + - [account_objects method][] + +{% raw-partial file="/docs/_snippets/common-links.md" /%}