diff --git a/content/concepts/accounts/account-creating.md b/content/concepts/accounts/account-creating.md new file mode 100644 index 0000000000..83d93dc5fe --- /dev/null +++ b/content/concepts/accounts/account-creating.md @@ -0,0 +1,43 @@ +# Creating Accounts + +There is not a dedicated "create account" transaction. The `Payment` transaction automatically creates a new account if a payment sends XRP equal to or greater than the account reserve to a mathematically valid address that does not already have an account. This is called _funding_ an account, and creates an AccountRoot object 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 is possible that no one has the secret key, in which case the account is a black hole 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. (For example, you can use the `wallet_propose` method to do this.) + +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 (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. + + + +## Transaction History + +In the XRP Ledger, transaction history is tracked by a "thread" of transactions linked by a transaction's identifying hash and the ledger index. The `AccountRoot` ledger object has the identifying hash and ledger of the transaction that most recently modified it; the metadata of that transaction includes the previous state of the `AccountRoot` node, so it is possible to iterate through the history of a single account this way. This transaction history includes any transactions that modify the `AccountRoot` node directly, including: + +- Transactions sent by the account, because they modify the account's `Sequence` number. These transactions also modify the account's XRP balance because of the [transaction cost](../transactions/transaction-cost.md). +- Transactions that modified the account's XRP balance, including incoming `Payment` transactions and other types of transactions such as `PaymentChannelClaim` and `EscrowFinish`. + +The _conceptual_ transaction history of an account also includes transactions that modified the account's owned objects and non-XRP balances. These objects are separate ledger objects, each with their own thread of transactions that affected them. If you have an account's full ledger history, you can follow it forward to find the ledger objects created or modified by it. A "complete" transaction history includes the history of objects owned by a transaction, such as: + +- `RippleState` objects (Trust Lines) connected to the account. +- `DirectoryNode` objects, especially the owner directory tracking the account's owned objects. +- `Offer` objects, representing the account's outstanding currency-exchange orders in the decentralized exchange +- `PayChannel` objects, representing asynchronous payment channels to and from the account +- `Escrow` objects, representing held payments to or from the account that are locked by time or a crypto-condition. +- `SignerList` objects, representing lists of addresses that can authorize transactions for the account by multi-signing. + + +## Address Encoding + +**Tip:** These technical details are only relevant for people building low-level library software for XRP Ledger compatibility! + +[[Source]](https://github.com/ripple/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. + diff --git a/content/concepts/accounts/account-deleting.md b/content/concepts/accounts/account-deleting.md new file mode 100644 index 0000000000..a314fbb1ec --- /dev/null +++ b/content/concepts/accounts/account-deleting.md @@ -0,0 +1,23 @@ +# Deleting Accounts + +The DeletableAccounts amendment (enabled 2020-05-08) made it possible to delete accounts. + +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 objects (as a sender or receiver): + - `Escrow` + - `PayChannel` + - `RippleState` + - `Check` +- The account must own fewer than 1000 objects in the ledger. +- The `AccountDelete` transaction must pay a special transaction cost equal to at least the owner reserve for one item (currently 2 XRP). + +After an account is deleted, you can recreate the account in the ledger through the normal method of creating accounts. An account that has been deleted and recreated is no different than an account created for the first time. + +**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, submit the transaction with `fail_hard` enabled. + +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 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** to distinguish payments from and to their customers while only using one (or a handful) of accounts in the XRP Ledger. + diff --git a/content/concepts/accounts/account-structure.md b/content/concepts/accounts/account-structure.md new file mode 100644 index 0000000000..1375a60186 --- /dev/null +++ b/content/concepts/accounts/account-structure.md @@ -0,0 +1,24 @@ +# 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 account reserve. +- 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. +- A **history of transactions** that affected this account and its balances. +- One or more ways to authorize 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. (Stored separately from the account's core data.) + +In the ledger's data tree, an account's core data is stored in the AccountRoot ledger object type. An account can also be the owner (or partial owner) of several other types of data. + +**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 are not stored in an XRP Ledger Account itself; each such asset is stored in an accounting relationship called a "Trust Line" that connects two parties. + +## Address Encoding + +**Tip:** These technical details are only relevant for people building low-level library software for XRP Ledger compatibility! + +[[Source]](https://github.com/ripple/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. diff --git a/content/concepts/accounts/account-types.md b/content/concepts/accounts/account-types.md new file mode 100644 index 0000000000..c0827a07c9 --- /dev/null +++ b/content/concepts/accounts/account-types.md @@ -0,0 +1,80 @@ +# Account Types + +In the XRP Ledger, financial institutions typically use multiple XRP Ledger accounts to minimize the risk associated with a compromised secret key. The industry standard is to separate roles as follows: + +* One *issuing account*, also known as a "cold wallet." This account is the hub of the financial institution's accounting relationships in the ledger, but sends as few transactions as possible. +* One or more *operational accounts*, also known as "hot wallets." Automated, internet-connected systems use the secret keys to these accounts to conduct day-to-day business like transfers to customers and partners. +* Optional *standby accounts*, also known as "warm wallets." Trusted human operators use these accounts to transfer money to the operational accounts. + +## Issuing Account + +The issuing account is like a vault. Partners, customers, and operational accounts create trust lines to the issuing account, but this account sends as few transactions as possible. Periodically, a human operator creates and signs a transaction from the issuing account to refill the balances of a standby or operational account. Ideally, the secret key used to sign these transactions should never be accessible from any internet-connected computer. + +Unlike a vault, the issuing account 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 account without needing a secret key. + +### Issuing Account Compromise + +If a malicious actor learns the secret key behind a institution's issuing account, 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 account, the institution must create a new issuing account, and all users who have trust lines to the old issuing account must create new trust lines with the new account. + +### Multiple Issuing Accounts + +A financial institution can issue more than one type of token in the XRP Ledger from a single issuing account. However, there are some settings that apply equally to all (fungible) tokens issued from an account, including the percentage for [transfer fees](../tokens/transfer-fees.md) and the [global freeze](../tokens/freezing-tokens.md) status. If the financial institution wants the flexibility to manage settings differently for each type of token, the institution must multiple issuing accounts. + + +## Operational Accounts + +An operational account 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 account 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 account. + +Each operational account has a limited balance of tokens and XRP. When the balance of an operational account gets low, the financial institution refills it by sending a payment from the issuing account or a standby account. + +### Operational Account Compromise + +If a malicious actor learns the secret key behind an operational account, the financial institution can only lose as much as that operational account holds. The institution can switch to a new operational account with no action from customers and partners. + + +## Standby Accounts + +Another optional step that an institution can take to balance risk and convenience is to use "standby accounts" as an intermediate step between the issuing account and operational accounts. The institution can fund additional XRP Ledger accounts as standby accounts, whose keys are not available to always-online servers, but are entrusted to different trusted users. + +When an operational account is running low on funds (either tokens or XRP), a trusted user can use a standby account to refill the operational account's balance. When a standby accounts run low on funds, the institution can use the issuing account to send more funds to a standby account in a single transaction, and the standby accounts can distribute those funds among themselves if necessary. This improves security of the issuing account, allowing it to make fewer total transactions, without leaving too much money in the control of a single automated system. + +As with operational accounts, a standby account must have an accounting relationship with the issuing account, and not with customers or partners. All precautions that apply to operational accounts also apply to standby accounts. + +### Standby Account Compromise + +If a standby account is compromised, the consequences are like an operational account being compromised. A malicious actor can steal any balances possessed by the standby account, and the financial institution can change to a new standby account with no action from customers and partners. + +## Funds Lifecycle + +When a token issuer follows this separation of roles, funds tend to flow in specific directions, as in the following diagram: + + + +The issuing account creates tokens by sending payments to standby accounts. These tokens have negative value from the perspective of the issuing account, since they (often) represent obligations. The same tokens have positive value from other perspectives, including from the perspective of a standby account. + +The standby accounts, which are operated by actual humans, send those tokens to operational accounts. This step allows the issuing account to be used as little as possible after this point, while having at least some tokens available on standby. + +Operational accounts, 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 with sufficient limits. + +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. + + \ No newline at end of file diff --git a/content/concepts/accounts/accounts.md b/content/concepts/accounts/accounts.md new file mode 100644 index 0000000000..1b866c6813 --- /dev/null +++ b/content/concepts/accounts/accounts.md @@ -0,0 +1,28 @@ +--- +html: accounts.html +parent: concepts.html +blurb: The XRP Ledger is a blockchain that records transactions of XRP and other tokens between accounts. +labels: + - Accounts +--- +# Accounts + +An "Account" in the XRP Ledger represents a holder of XRP and a sender of transactions. + +## 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 account reserve. +- 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. +- A **history of transactions** that affected this account and its balances. +- One or more ways to authorize 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. (Stored separately from the account's core data.) + +In the ledger's data tree, an account's core data is stored in the AccountRoot ledger object type. An account can also be the owner (or partial owner) of several other types of data. + +**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 are not stored in an XRP Ledger Account itself; each such asset is stored in an accounting relationship called a "Trust Line" that connects two parties. + diff --git a/content/concepts/accounts/addresses.md b/content/concepts/accounts/addresses.md new file mode 100644 index 0000000000..41d1b786cc --- /dev/null +++ b/content/concepts/accounts/addresses.md @@ -0,0 +1,46 @@ +## Addresses + +Accounts in the XRP Ledger are identified by an address in the XRP Ledger's base58 format. The address is derived from the account's master [public key](https://en.wikipedia.org/wiki/Public-key_cryptography), which is in turn derived from a secret key. An address is represented as a string in JSON and has the following characteristics: + +* Between 25 and 35 characters in length +* Starts with the character `r` +* Uses alphanumeric characters, excluding the number "`0`" capital letter "`O`", capital letter "`I`", and lowercase letter "`l`" +* Case-sensitive +* Includes a 4-byte checksum so that the probability of generating a valid address from random characters is approximately 1 in 232 + +> **Note:** The XRP community has proposed an **X**-address format that "packs" a destination tag into the address. These addresses start with an `X` (for the mainnet) or a `T` (for the [testnet](../networks/parallel-networks.md)). Exchanges and wallets can use X-addresses to represent all the data a customer needs to know in one value. For more information, see the [X-address format site](https://xrpaddress.info/) and [codec](https://github.com/xrp-community/xrpl-tagged-address-codec). +> +> The XRP Ledger protocol only supports "classic" addresses natively, but many client libraries support X-addresses too. + + +For more information, see [Accounts](accounts.md). + + +Any valid address can become an account in the XRP Ledger by being funded. You can also use an address that has not been funded to represent a regular key or a member of a signer list. 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.) + +For more technical details of how to calculate an XRP Ledger address, see [Address Encoding](#address-encoding). + + +## Address Encoding + +**Tip:** These technical details are only relevant for people building low-level library software for XRP Ledger compatibility! + +[[Source]](https://github.com/ripple/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. + + +### 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](ripplestate.html) 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/ripple/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 | diff --git a/content/concepts/accounts/balances.md b/content/concepts/accounts/balances.md new file mode 100644 index 0000000000..19e6c9db4e --- /dev/null +++ b/content/concepts/accounts/balances.md @@ -0,0 +1,3 @@ +# Balances + +Placeholder for details of the account balances. \ No newline at end of file diff --git a/content/concepts/accounts/cryptographic-keys.md b/content/concepts/accounts/cryptographic-keys.md new file mode 100644 index 0000000000..492abe4159 --- /dev/null +++ b/content/concepts/accounts/cryptographic-keys.md @@ -0,0 +1,257 @@ +# Cryptographic Keys + +In the XRP Ledger, a digital signature _authorizes_ a [transaction](../transactions/transactions.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, regular key pair, or a member of a signer list, 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 keypairs 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 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. + +{{ include_svg("../../../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. + + + +### 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 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 in the rippled APIs and some [other XRP Ledger software](../xrpl/xrpl-ecosystem.md). 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 has 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 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 has 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 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 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 that funds its reserve requirement. 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 or a member of a signer list. + +### Key Type + +The XRP Ledger supports more than one cryptographic signing algorithm. 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. + + + +**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 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. + +- Disable the master key pair. + +- Permanently give up the ability to [freeze](../tokens/freezing-tokens.md#no-freeze). + +- Send a special key reset transaction with a transaction cost of 0 XRP. + +A regular key or multi-signature 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](account-deleting.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 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. 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. + + + +## 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 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/ripple/rippled/blob/develop/src/ripple/protocol/Seed.h) + - [General & Ed25519 key derivation](https://github.com/ripple/rippled/blob/develop/src/ripple/protocol/impl/SecretKey.cpp) + - [secp256k1 key derivation](https://github.com/ripple/rippled/blob/develop/src/ripple/protocol/impl/SecretKey.cpp) +- In Python 3 in [this repository's code samples section]({{target.github_forkurl}}/blob/{{target.github_branch}}/content/_code-samples/key-derivation/py/key_derivation.py). +- In JavaScript in the [`ripple-keypairs`](https://github.com/ripple/ripple-keypairs/) package. + +### Ed25519 Key Derivation +[[Source]](https://github.com/ripple/rippled/blob/fc7ecd672a3b9748bfea52ce65996e324553c05f/src/ripple/protocol/impl/SecretKey.cpp#L203 "Source") + +{{ include_svg("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/ripple/rippled/blob/develop/src/ripple/protocol/impl/SecretKey.cpp "Source") + +{{ include_svg("../../../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/ripple/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. + + \ No newline at end of file diff --git a/content/concepts/accounts/deposit-authorization.md b/content/concepts/accounts/deposit-authorization.md new file mode 100644 index 0000000000..cdbe58a478 --- /dev/null +++ b/content/concepts/accounts/deposit-authorization.md @@ -0,0 +1,111 @@ +# Deposit Authorization + +_(Added by the DepositAuth amendment.)_ + +Deposit Authorization is an optional [account](accounts.md) setting in the XRP Ledger. If enabled, Deposit Authorization blocks all transfers from strangers, including transfers of XRP and [tokens](../tokens/tokens.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 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, escrow, and payment channels. 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. +- Keep the Default Ripple flag in its default (disabled) state. Do not enable rippling on any trust lines. When sending TrustSet transactions, always use the `tfSetNoRipple` flag. +- Do not place Offers. 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, 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 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: + +{% include '_snippets/depositauth-semantics-table.html' %} + + + +## 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). + + + +## 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. + +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 to the ledger, which increases the owner reserve 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. + + + +### 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. + + \ No newline at end of file diff --git a/content/concepts/accounts/history.md b/content/concepts/accounts/history.md new file mode 100644 index 0000000000..e3506c88ea --- /dev/null +++ b/content/concepts/accounts/history.md @@ -0,0 +1,3 @@ +# History + +Placeholder for details of account history. \ No newline at end of file diff --git a/content/concepts/accounts/reserves.md b/content/concepts/accounts/reserves.md new file mode 100644 index 0000000000..79f05d43cd --- /dev/null +++ b/content/concepts/accounts/reserves.md @@ -0,0 +1,67 @@ +# 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. You cannot send this XRP to other addresses. To fund a new address, you must send that address enough XRP to meet the reserve requirement. + +The current minimum reserve requirement is **10 XRP**. (This is the cost of an address that owns no other objects in the ledger.) Each new account must set aside this much XRP. Some of this XRP can be recovered by deleting the account. + +The [Fee Voting](../xrpl/fee-voting.md) process can change the reserve requirement if enough validators agree to new reserve settings. + + +## Base Reserve and Owner Reserve + +The reserve requirement is divided into two parts: + +* The **Base Reserve** is a minimum amount of XRP that is required for each address in the ledger. Currently, this is 10 XRP (`10000000` drops). +* The **Owner Reserve** is an increase to the reserve requirement for each object that the address owns in the ledger. Currently, this is 2 XRP (`2000000` drops) per item. + + +### Owner Reserves + +Many objects in the ledger are owned by a particular address, and count toward the reserve requirement of that address. When objects are removed from the ledger, they no longer count against their owner's reserve requirement. + +- Offers are owned by the address that placed them. Transaction processing automatically removes Offers that are fully consumed or found to be unfunded. Alternatively, the owner can cancel an Offer by sending an `OfferCancel` transaction, or by sending an `OfferCreate` transaction that contains an `OfferSequence` parameter. +- Trust lines are shared between two addresses. The owner reserve can apply to one or both of the addresses, depending on whether the fields that address controls are in their default state. + + + +- A SignerList counts as 1 object for purposes of the owner reserve (since the `MultiSignReserve amendment` activated in April 2019). + + +- Held Payments (Escrow) are owned by the address that placed them. +- Payment Channels are owned by the address that created them. +- Owner directories list all the ledger objects that contribute to an address's owner reserve. However, the owner directory itself does not count towards the reserve. +- Checks are owned by the address that created them (the sender, not the destination). + + +#### Owner Reserve Edge Cases + +The XRP Ledger considers an `OfferCreate` transaction to be an explicit statement of willingness to hold an asset. Consuming the offer automatically creates a trust line (with limit 0, and a balance above that limit) for the `taker_pays` currency if such a trust line does not exist. However, if the offer's owner does not hold enough XRP to also meet the owner reserve requirement of the new trust line, the offer is considered unfunded. See also: `Lifecycle of an Offer`. + + +## 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. + +When an address holds less XRP than its current reserve requirement, it cannot send new transactions that would transfer XRP to others, or increase its own reserve. Even so, the address continues to exist in the ledger and can send other transactions as long as it has enough XRP to pay the transaction cost. The address can become able to send all types of transactions again if it receives enough XRP to meet its reserve requirement again, or if the [reserve requirement decreases](#changing-the-reserve-requirements) to less than the address's XRP holdings. + +**Tip:** When an address is below the reserve requirement, it can send new `OfferCreate transactions` to acquire more XRP, or other currencies on its existing trust lines. These transactions cannot create new trust lines or Offer nodes in the ledger, so they can only execute trades that 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](../xrpl/fee-voting.md) for more information. + + \ No newline at end of file diff --git a/content/concepts/accounts/sequence.md b/content/concepts/accounts/sequence.md new file mode 100644 index 0000000000..1be56d77fd --- /dev/null +++ b/content/concepts/accounts/sequence.md @@ -0,0 +1,3 @@ +# Sequence + +Placeholder for details of sequence with regard to account transactions. \ No newline at end of file diff --git a/content/concepts/fees.md b/content/concepts/fees.md new file mode 100644 index 0000000000..6d1e447419 --- /dev/null +++ b/content/concepts/fees.md @@ -0,0 +1,27 @@ +# Fees (Disambiguation) + +The XRP Ledger is a decentralized ledger, secured by cryptography and powered by a distributed peer-to-peer network of servers. This means that no one party, not even Ripple, can require a fee for access to the network. + +However, the rules of the XRP Ledger include several types of fees, including neutral fees which protect the ledger against abuse. These neutral fees are not paid to anyone. There are also several optional ways that users can collect fees from each other, both inside and outside the XRP Ledger. + + +## In the Ledger + +### Neutral Fees + +The _**transaction cost**_ (sometimes called the transaction fee) is a miniscule amount of XRP destroyed to send a transaction. This cost scales with the load of the network, which protects the peer-to-peer network from spam. See [Transaction Cost](./transactions/transaction-cost.md) for more information. + +The _**reserve requirement**_ is a minimum amount of XRP that an account must hold. It increases with the number of objects the account owns in the ledger. This disincentivizes users from increasing the size of the ledger carelessly or maliciously. See [Reserves](./accounts/reserves.md) for more information. + +### Optional Fees + +_**Transfer fees**_ are optional percentage fees that issuers can charge to transfer the currencies they issue to other addresses within the XRP Ledger. See [Transfer Fees](./tokens/transfer-fees.md) for more information. + +_**Trust line quality**_ is a setting that allows an account to value balances on a trust line at higher or lower than face value. This can lead to situations that are like charging a fee. Trust line quality does not apply to XRP, which is not tied to a trust line. + + +## Outside the Ledger + +Although the fees described above are the only fees built into the XRP Ledger, people can still invent ways to charge fees associated with the ledger. For example, financial institutions commonly charge their customers to send money into and out of the XRP Ledger. + +Many other fees are also possible. Businesses might charge for access to a client application, maintenance of non-XRP Ledger accounts, exchange services (especially when buying XRP on a private market instead of within the XRP Ledger's decentralized exchange) and any number of other services. Always be aware of the fee schedule before doing business with any financial institution. \ No newline at end of file diff --git a/content/concepts/networks/federated-sidechains.md b/content/concepts/networks/federated-sidechains.md new file mode 100644 index 0000000000..eb344e1909 --- /dev/null +++ b/content/concepts/networks/federated-sidechains.md @@ -0,0 +1,76 @@ +# Federated Sidechains + +_Federated Sidechains are available as an Engineering Preview and can be used to develop and test using `rippled` 1.8.0._ + +A sidechain is an independent ledger with its own consensus algorithm and transaction types and rules. It acts as its own blockchain. Federation enables value in the form of XRP and other tokens to move efficiently between a sidechain and an XRP Ledger _mainchain_ (usually Mainnet, but could be [Testnet or Devnet](parallel-networks.html) for testing). Federated sidechains operate without compromising the speed, efficiency, and throughput of the public Mainnet. + +Federated sidechains enable developers to launch new features and innovative applications using the foundation of XRP Ledger technology. Sidechains can customize the XRP Ledger protocol to the needs of a specific use case or project and run it as its own blockchain. Here are a few examples: + +* Build a smart contract layer, powered by an engine compatible with the Ethereum Virtual Machine (EVM), web assembly, or a Move VM. For example, a [smart sidechain with Hooks](https://hooks-testnet.xrpl-labs.com/) enabled. +* Build your own algorithmic stable coin with customised ledger types and transaction rules. +* Build permissioned or nearly permissionless, centralized or largely decentralized ledgers whose assets can be traded on the Mainnet [decentralized exchange](decentralized-exchange.html). + +## How Federated Sidechains Work + + +A sidechain is an independent ledger with its own consensus algorithm and transaction types and rules. Each sidechain is run by its own set of servers (including validators) and does not rely on the validators on the Mainnet for transactions on the sidechain. + +Each sidechain has two door accounts, one on the sidechain and one on the mainchain, that are controlled by the federators on the sidechain. The federators listen for transactions to and from both of these door accounts. + +The sidechain has _federators_ who jointly control the door accounts on both networks using [multi-signing](multi-signing.html) so that 80% of federators must approve a transaction. In many cases, the federators should also be the trusted validators of the sidechain. + +When a door account receives a transaction on either the sidechain or the mainchain, the federators create a mirror transaction on the other chain. (For example, if you send XRP _to_ the mainchain door account, the federators create a transaction on the sidechain to send XRP _from_ the sidechain door account to the intended recipient.) The federators sign the transaction and broadcast it to each other. Simultaneously, federators also listen for signed transactions from other federators and collect them. + +When 80% of the federators have signed the transaction, they submit it to the sidechain or mainchain as appropriate. This way, assets that the mainchain door account holds can be allocated to others on the sidechain, and assets that sidechain door account receives can be sent to others on the mainchain. + +Transactions within the sidechain are not visible to the servers on the mainchain. + + +## Terminology + +Below is an alphabetical list of terms and their definitions. + +_Door account_: An account controlled by the federators. There are two door accounts: one on the mainchain and one on the sidechain. Cross chain transactions are started by users sending assets to a door account. Mainchain to sidechain transactions cause the balance to increase on the mainchain door account and the balance to decrease on the sidechain door account. It is called a "door" because it is the mechanism to move assets from one chain to another—much like going between rooms in a house requires stepping through a door. + +_Federator_: A server on the sidechain that listens for triggering transactions on both the mainchain and the sidechain. Each federator has a signing key associated with it that is used to sign transactions. A transaction must be signed by a quorum of federators before it can be submitted. Federators are responsible for creating and signing valid response transactions, collecting signatures from other federators, and submitting transactions to the mainchain and sidechain. + +_Mainchain_: The blockchain where assets originate and where assets are held while being used on the sidechain. For most sidechains, the mainchain is the XRP Ledger Mainnet, Testnet, or Devnet. + +_Response transaction_: A transaction submitted by the federators in reaction to a triggering transaction. In most cases, the response transaction occurs on the opposite chain as the triggering transaction. However, there are some exceptions for handling failed transactions. + +_Sidechain_: An XRP Ledger sidechain is another blockchain based on XRP Ledger technology. A _federated_ sidechain provides a way to transfer assets from a mainchain to the sidechain and back. A sidechain can use an exact copy of the XRP Ledger's protocol or it can make changes, including to the [consensus algorithm](consensus.html), [transaction types](transaction-types.html), and other rules. Sidechains have separate history, rules, and validators than the mainchain. Proxy assets are issued in the sidechain, with the equivalent assets held by a door account on the mainchain. Proxy assets on the sidechain can be sent back to the mainchain and unlocked from the control of the federators. + +_Triggering transaction_: A transaction that causes the federators to start the process of signing and submitting a new response transaction. For example, sending XRP to the mainchain's door account is a triggering transaction that causes the federators to submit a new transaction on the sidechain. + +## How to Set Up a Federated Sidechain + +Federated Sidechains are currently available as an Engineering Preview so you can experiment and explore the potential of sidechains. You can connect sidechains to the XRP Ledger Testnet, Devnet, or Mainnet as long as [the servers](xrpl-servers.html) in the mainchain network are running version 1.8.0 or higher. + +**Caution:** You can connect sidechains to the XRP Ledger Mainnet to develop and test with small amounts; it is not recommended for production use cases until federated sidechains are available in a release. + +Setting up a sidechain involves the following high-level steps: + +1. Clone the `rippled` source code and check out the `sidechain` branch: https://github.com/ripple/rippled/tree/sidechain. +2. Customize the source code for your sidechain. For example, you may want to write custom [transaction types](transaction-types.html). Note that this is an important and non-trivial task. +3. Each sidechain federator has its own configuration file that must be updated to include the following information: + - `[sidechain]` stanza - add details such as signing key, mainchain account, and the mainchain address (IP and port) to listen to. + - `[sidechain_assets]` stanza - define assets that can be used for cross-chain transactions (XRP or [issued tokens](issued-currencies.html)), exchange rate for the assets, and optional refund penalty to discourage transactions that may default. + - [sidechain_federators] stanza - list of federators public keys to be used for signing. This list is common for all federators on the sidechain. +4. Set up door accounts to enable cross chain transactions. This involves the following steps (on _both_ chains): + - Create and fund the door accounts. + - [Set up the SignerList](set-up-multi-signing.html) for the door account. + - Create three [tickets](tickets.html) for error handling. + - And finally, [disable the master key pair](disable-master-key-pair.html) to the door account to ensure that the federators jointly control the door account. + + Note that it is important to perform this final step only after successful completion of the previous steps. + + +The _Sidechain Launch Kit_ is a commandline tool that simplifies setting up federated sidechains and can be used to quickly spin up a sidechain on your local machine. The launch kit also installs an interactive Sidechain Shell that enables you to interact with the sidechain. + +[Sidechain Launch Kit >](https://github.com/xpring-eng/sidechain-launch-kit) + + +## See Also + +- **Concepts:** + - [Federated Sidechains Video](https://www.youtube.com/embed/NhH4LM8NxgY) diff --git a/content/concepts/networks/parallel-networks.md b/content/concepts/networks/parallel-networks.md new file mode 100644 index 0000000000..016f064d46 --- /dev/null +++ b/content/concepts/networks/parallel-networks.md @@ -0,0 +1,42 @@ +# Parallel Networks + +There is one production XRP Ledger peer-to-peer network, and all business that takes place on the XRP Ledger occurs within the production network—the Mainnet. + +To help members of the XRP Ledger community interact with XRP Ledger technology without affecting anything on the Mainnet, Ripple hosts two alternative networks, or altnets: the Testnet and the Devnet. Here's a breakdown of all three networks: + +| Network | Upgrade Cadence | Description | +|:--------|:----------------|:-------------------------------------------------| +| Mainnet | Stable releases | _The_ [XRP Ledger](xrp-ledger-overview.html), a decentralized cryptographic ledger powered by a network of peer-to-peer servers and the home of [XRP](xrp.html). | +| Testnet | Stable releases | An "alternate universe" network that acts as a testing ground for software built on the XRP Ledger, without impacting production XRP Ledger users and without risking real money. The [amendment status](known-amendments.html) of the Testnet is intended to closely mirror the Mainnet, although slight variations in timing may occur due to the unpredictable nature of decentralized systems. | +| Devnet | Beta releases | A preview of coming attractions, where unstable changes to the core XRP Ledger software may be tested out. Developers can use this altnet to interact with and learn about planned new XRP Ledger features and amendments that are not yet enabled on the Mainnet. | +| NFT-Devnet | [XLS-20 pre-release](https://github.com/ripple/rippled/tree/xls20) | A preview of the [XLS-20d](https://github.com/XRPLF/XRPL-Standards/discussions/46) standard for non-fungible tokens on the XRP Ledger. | +| [Hooks Testnet V2](https://hooks-testnet-v2.xrpl-labs.com/) | [Hooks server](https://github.com/XRPL-Labs/xrpld-hooks) | A preview of on-chain smart contract functionality using [hooks](https://write.as/xumm/xrpl-labs-is-working-on-the-transaction-hooks-amendment-for-the-xrp-ledger). | + +Each test network has its own separate supply of test XRP, which is [given away for free](xrp-testnet-faucet.html) to parties interested in experimenting with the XRP Ledger and developing applications and integrations. Test XRP does not have real-world value and is lost when the network is reset. + +**Caution:** Unlike the XRP Ledger Mainnet, test networks are usually _centralized_ and there are no guarantees about the stability and availability of these networks. They have been and continue to be used to test various properties of server configuration, network topology, and network performance. + + +## Parallel Networks and Consensus + +The main factor in determining which network a server follows is its configured UNL—the list of validators it trusts not to collude. Each server uses its configured UNL to know which ledger to accept as the truth. When different consensus groups of `rippled` instances only trust other members of the same group, each group continues as a parallel network. Even if malicious or misbehaving computers connect to both networks, the consensus process overrides the confusion as long as the members of each network are not configured to trust members of another network in excess of their quorum settings. + +Ripple runs the main servers in the Testnet, Devnet, and NFT-Devnet; you can also [connect your own `rippled` server to these networks](connect-your-rippled-to-the-xrp-test-net.html). The Testnet and Devnet do not use diverse, censorship-resistant sets of validators. This makes it possible for Ripple to reset the Testnet or Devnet on a regular basis. + + +## See Also + +- **Tools:** + - [XRP Testnet Faucet](xrp-test-net-faucet.html) +- **Concepts:** + - [Introduction to Consensus](intro-to-consensus.html) + - [Amendments](amendments.html) +- **Tutorials:** + - [Connect Your `rippled` to the XRP Testnet](connect-your-rippled-to-the-xrp-test-net.html) + - [Use rippled in Stand-Alone Mode](use-stand-alone-mode.html) +- **References:** + - [server_info method][] + - [consensus_info method][] + - [validator_list_sites method][] + - [validators method][] + - [Daemon Mode Options](commandline-usage.html#daemon-mode-options) \ No newline at end of file diff --git a/content/concepts/networks/xrpl-networks.md b/content/concepts/networks/xrpl-networks.md new file mode 100644 index 0000000000..53fbdae8e7 --- /dev/null +++ b/content/concepts/networks/xrpl-networks.md @@ -0,0 +1,3 @@ +# The XRP Ledger Networks + +Placeholder for XRPL networks documentation. \ No newline at end of file diff --git a/content/concepts/server/clio-server.md b/content/concepts/server/clio-server.md new file mode 100644 index 0000000000..bc733ad0d8 --- /dev/null +++ b/content/concepts/server/clio-server.md @@ -0,0 +1,3 @@ +# Clio Server + +Placeholder for Clio server documentation. \ No newline at end of file diff --git a/content/concepts/server/invariant-checking.md b/content/concepts/server/invariant-checking.md new file mode 100644 index 0000000000..d5b4d18967 --- /dev/null +++ b/content/concepts/server/invariant-checking.md @@ -0,0 +1,145 @@ +# Invariant Checking + +Invariant checking is a safety feature of the XRP Ledger. It consists of a set of checks, separate from normal transaction processing, that guarantee that certain _invariants_ hold true across all transactions. + +Like many safety features, we all hope that invariant checking never actually needs to do anything. However, it can be useful to understand the XRP Ledger's invariants because they define hard limits on the XRP Ledger's transaction processing, and to recognize the problem in the unlikely event that a transaction fails because it violated an invariant check. + +Invariants should not trigger, but they ensure the XRP Ledger's integrity from bugs yet to be discovered or even created. + + +## Why it Exists + +- The source code for the XRP Ledger is complicated and vast; there is a high potential for code to execute incorrectly. +- The cost of incorrectly executing a transaction is high and not acceptable by any standards. + +Specifically, incorrect transaction executions could create invalid or corrupt data that later consistently crashes servers in the network by sending them into an "impossible" state which could halt the entire network. + +The processing of incorrect transaction would undermine the value of trust in the XRP Ledger. Invariant checking provides value to the entire XRP Ledger because it adds the feature of reliability. + + + +## How it Works + +The invariant checker is a second layer of code that runs automatically in real-time after each transaction. Before the transaction's results are committed to the ledger, the invariant checker examines those changes for correctness. If the transaction's results would break one of the XRP Ledger's strict rules, the invariant checker rejects the transaction. Transactions that are rejected this way have the result code `tecINVARIANT_FAILED` and are included in the ledger with no effects. + +To include the transaction in the ledger with a `tec`-class code, some minimal processing is necessary. If this minimal processing still breaks an invariant, the transaction fails with the code `tefINVARIANT_FAILED` instead, and is not included in the ledger at all. + + +## Active Invariants + +The XRP Ledger checks all the following invariants on each transaction: + +[[Source]](https://github.com/ripple/rippled/blob/023f5704d07d09e70091f38a0d4e5df213a3144b/src/ripple/app/tx/impl/InvariantCheck.h#L92 "Source") + +- [Transaction Fee Check](#transaction-fee-check) + +[[Source]](https://github.com/ripple/rippled/blob/023f5704d07d09e70091f38a0d4e5df213a3144b/src/ripple/app/tx/impl/InvariantCheck.h#L118 "Source") + +- [XRP Not Created](#xrp-not-created) + +[[Source]](https://github.com/ripple/rippled/blob/023f5704d07d09e70091f38a0d4e5df213a3144b/src/ripple/app/tx/impl/InvariantCheck.h#L146 "Source") + +- [Account Roots Not Deleted](#account-roots-not-deleted) + +[[Source]](https://github.com/ripple/rippled/blob/023f5704d07d09e70091f38a0d4e5df213a3144b/src/ripple/app/tx/impl/InvariantCheck.h#L173 "Source") + +- [XRP Balance Checks](#xrp-balance-checks) + +[[Source]](https://github.com/ripple/rippled/blob/023f5704d07d09e70091f38a0d4e5df213a3144b/src/ripple/app/tx/impl/InvariantCheck.h#L197 "Source") + +- [Ledger Entry Types Match](#ledger-entry-types-match) + +[[Source]](https://github.com/ripple/rippled/blob/023f5704d07d09e70091f38a0d4e5df213a3144b/src/ripple/app/tx/impl/InvariantCheck.h#L224 "Source") + +- [No XRP Trust Lines](#no-xrp-trust-lines) + +[[Source]](https://github.com/ripple/rippled/blob/023f5704d07d09e70091f38a0d4e5df213a3144b/src/ripple/app/tx/impl/InvariantCheck.h#L251 "Source") + +- [No Bad Offers](#no-bad-offers) + +[[Source]](https://github.com/ripple/rippled/blob/023f5704d07d09e70091f38a0d4e5df213a3144b/src/ripple/app/tx/impl/InvariantCheck.h#L275 "Source") + +- [No Zero Escrow](#no-zero-escrow) + +[[Source]](https://github.com/ripple/rippled/blob/023f5704d07d09e70091f38a0d4e5df213a3144b/src/ripple/app/tx/impl/InvariantCheck.h#L300 "Source") + +- [Valid New Account Root](#valid-new-account-root) + + +### Transaction Fee Check + +- **Invariant Condition(s):** + - The [transaction cost](transaction-cost.html) amount must never be negative, nor larger than the cost specified in the transaction. + + +### XRP Not Created + +- **Invariant Condition(s):** + - A transaction must not create XRP and should only destroy the XRP [transaction cost](transaction-cost.html). + + +### Account Roots Not Deleted + +- **Invariant Condition(s):** + - An [account](accounts.html) cannot be deleted from the ledger except by an [AccountDelete transaction][]. + - A successful AccountDelete transaction always deletes exactly 1 account. + + +### XRP Balance Checks + +- **Invariant Condition(s):** + - An account's XRP balance must be of type XRP, and it cannot be less than 0 or more than 100 billion XRP exactly. + + +### Ledger Entry Types Match + +- **Invariant Condition(s):** + - Corresponding modified ledger entries should match in type and added entries should be a [valid type](ledger-object-types.html). + + +### No XRP Trust Lines + +- **Invariant Condition(s):** + - [Trust lines](trust-lines-and-issuing.html) using XRP are not allowed. + + +### No Bad Offers + +- **Invariant Condition(s):** + - [Offers](offer.html) should be for non-negative amounts and must not be XRP to XRP. + + +### No Zero Escrow + +- **Invariant Condition(s):** + - An [escrow](escrow-object.html) entry must hold more than 0 XRP and less than 100 billion XRP. + + +### Valid New Account Root + +- **Invariant Condition(s):** + - A new [account root](accountroot.html) must be the consequence of a payment. + - A new account root must have the right starting [sequence](basic-data-types.html#account-sequence). + - A transaction must not create more than one new [account](accounts.html). + + +## See Also + +- **Blog:** + - [Protecting the Ledger: Invariant Checking](https://xrpl.org/blog/2017/invariant-checking.html) + +- **Repository:** + - [Invariant Check.h](https://github.com/ripple/rippled/blob/023f5704d07d09e70091f38a0d4e5df213a3144b/src/ripple/app/tx/impl/InvariantCheck.h) + - [Invariant Check.cpp](https://github.com/ripple/rippled/blob/023f5704d07d09e70091f38a0d4e5df213a3144b/src/ripple/app/tx/impl/InvariantCheck.cpp) + - [System Parameters](https://github.com/ripple/rippled/blob/develop/src/ripple/protocol/SystemParameters.h#L43) + - [XRP Amount](https://github.com/ripple/rippled/blob/develop/src/ripple/basics/XRPAmount.h#L244) + - [Ledger Formats](https://github.com/ripple/rippled/blob/023f5704d07d09e70091f38a0d4e5df213a3144b/src/ripple/protocol/LedgerFormats.h#L36-L94) + + +- **Other:** + - [Authorized Trust Lines](authorized-trust-lines.html) + - [XRP Properties](xrp.html#xrp-properties) + - [Calculating Balance Changes for a Transaction](https://xrpl.org/blog/2015/calculating-balance-changes-for-a-transaction.html#calculating-balance-changes-for-a-transaction) + + + diff --git a/content/concepts/server/rippled-server.md b/content/concepts/server/rippled-server.md new file mode 100644 index 0000000000..2c3304d6e0 --- /dev/null +++ b/content/concepts/server/rippled-server.md @@ -0,0 +1,10 @@ +--- +html: rippled-server.html +parent: concepts.html +blurb: The XRP Ledger is a blockchain that records transactions of XRP and other tokens between accounts. +labels: + - Servers +--- +# rippled Server + +Placeholder for rippled server documentation. \ No newline at end of file diff --git a/content/concepts/server/server-modes.md b/content/concepts/server/server-modes.md new file mode 100644 index 0000000000..445f358614 --- /dev/null +++ b/content/concepts/server/server-modes.md @@ -0,0 +1,3 @@ +# Server Modes + +Placeholder for Server Mode documentation. \ No newline at end of file diff --git a/content/concepts/server/transaction-queue.md b/content/concepts/server/transaction-queue.md new file mode 100644 index 0000000000..4230c95f7e --- /dev/null +++ b/content/concepts/server/transaction-queue.md @@ -0,0 +1,67 @@ +# Transaction Queue + +The `rippled` server uses a transaction queue to help enforce the [open ledger cost](transaction-cost.html#open-ledger-cost). The open ledger cost sets a target number of transactions in a given ledger, and escalates the required transaction cost very quickly when the open ledger surpasses this size. Rather than discarding transactions that cannot pay the escalated transaction cost, `rippled` tries to put them in a transaction queue, which it uses to build the next ledger. + +## Transaction Queue and Consensus + +The transaction queue plays an important role in selecting the transactions that are included or excluded from a given ledger version in the consensus process. The following steps describe how the transaction queue relates to the [consensus process](consensus.html). + +{{ include_svg("img/consensus-with-queue.svg", "Transaction queue and consensus diagram") }} + +1. **Consensus Round 1** - Each validator proposes a set of transactions to be included in the next ledger version. Each also keeps a queue of candidate transactions not currently proposed. + +2. **Consensus Round 2** - If a validator removes a transaction from its proposal in later rounds, it adds that transaction to its queue. + +3. **Consensus Round N** - The consensus process continues until enough servers agree on a transaction set. + +4. **Validation** - Servers confirm that they built the same resulting ledger and declare it validated. + +5. **Building the Next Proposal** - Each validator prepares its proposal for the next ledger version, starting with queued transactions. + +6. **Adding to the Queue** - If the next proposed ledger is already full, incoming transactions are queued for a later ledger version. (Transactions that pay the [open ledger cost](transaction-cost.html#open-ledger-cost) can still get into the next proposed ledger even if it's "full", but the open ledger cost grows exponentially with each transaction added this way.) + + After this step, the process repeats from the beginning. + +**Note:** Technically, several of the steps described in the above process occur in parallel, because each server is always listening for new transactions, and starts preparing its next ledger proposal while the consensus process for the previous ledger version is ongoing. + +## Queuing Restrictions + +The `rippled` server uses a variety of heuristics to estimate which transactions are "likely to be included in a ledger." The current implementation uses the following rules to decide which transactions to queue: + +- Transactions must be properly-formed and [authorized](transaction-basics.html#authorizing-transactions) with valid signatures. +- Transactions with an `AccountTxnID` field cannot be queued. +- A single sending address can have at most 10 transactions queued at the same time. +- To queue a transaction, the sender must have enough XRP for all of the following: [Updated in: rippled 1.2.0][] + - Destroying the XRP [transaction cost](transaction-cost.html) as specified in the `Fee` fields of all the sender's queued transactions. The total amount among queued transactions cannot be more than the base account reserve (currently 10 XRP). (Transactions paying significantly more than the minimum transaction cost of 0.00001 XRP typically skip the queue and go straight into the open ledger.) + - Sending the maximum sum of XRP that all the sender's queued transactions could send. + - Keeping enough XRP to meet the account's [reserve requirements](reserves.html). +- If a transaction affects how the sending address authorizes transactions, no other transactions from the same address can be queued behind it. [New in: rippled 0.32.0][] +- If a transaction includes a `LastLedgerSequence` field, the value of that field must be at least **the current ledger index + 2**. + +### Fee Averaging + +[New in: rippled 0.33.0][] + +If a sending address has one or more transactions queued, that sender can "push" the existing queued transactions into the open ledger by submitting a new transaction with a high enough transaction cost to pay for all of them. Specifically, the new transaction must pay a high enough transaction cost to cover the [open ledger cost](transaction-cost.html#open-ledger-cost) of itself and each other transaction from the same sender before it in the queue. (Keep in mind that the open ledger cost increases exponentially each time a transaction pays it.) The transactions must still follow the other [queuing restrictions](#queuing-restrictions) and the sending address must have enough XRP to pay the transaction costs of all the queued transactions. + +This feature helps you work around a particular situation. If you submitted one or more transactions with a low cost that were queued, you cannot send new transactions from the same address unless you do one of the following: + +* Wait for the queued transactions to be included in a validated ledger, _or_ +* Wait for the queued transactions to be permanently invalidated if the transactions have the [`LastLedgerSequence` field](reliable-transaction-submission.html#lastledgersequence) set, _or_ +* [Cancel the queued transactions](cancel-or-skip-a-transaction.html) by submitting a new transaction with the same sequence number and a higher transaction cost. + +If none of the above occur, transactions can stay in the queue for a theoretically unlimited amount of time, while other senders can "cut in line" by submitting transactions with higher transaction costs. Since signed transactions are immutable, you cannot increase the transaction cost of the queued transactions to increase their priority. If you do not want to invalidate the previously submitted transactions, fee averaging provides a workaround. If you increase the transaction cost of your new transaction to compensate, you can ensure the queued transactions are included in an open ledger right away. + +## Order Within the Queue + +Within the transaction queue, transactions are ranked so that transactions paying a higher transaction cost come first. This ranking is not by the transactions' _absolute_ XRP cost, but by costs _relative to the [minimum cost for that type of transaction](transaction-cost.html#special-transaction-costs)_. Transactions that pay the same transaction cost are ranked in the order the server received them. Other factors may also affect the order of transactions in the queue; for example, transactions from the same sender are sorted by their `Sequence` numbers so that they are submitted in order. + +The precise order of transactions in the queue decides which transactions get added to the next in-progress ledger version in cases where there are more transactions in the queue than the expected size of the next ledger version. The order of the transactions **does not affect the order the transactions are executed within a validated ledger**. In each validated ledger version, the transaction set for that version executes in [canonical order](consensus.html#calculate-and-share-validations). + +**Note:** When `rippled` queues a transaction, the provisional [transaction response code](transaction-results.html) is `terQUEUED`. This means that the transaction is likely to succeed in a future ledger version. As with all provisional response codes, the outcome of the transaction is not final until the transaction is either included in a validated ledger, or [rendered permanently invalid](finality-of-results.html). + + +## See Also + +- [Transaction Cost](transaction-cost.html) for information on why the transaction cost exists and how the XRP Ledger enforces it. +- [Consensus](consensus.html) for a detailed description of how the consensus process approves transactions. diff --git a/content/concepts/server/xrpl-servers.md b/content/concepts/server/xrpl-servers.md new file mode 100644 index 0000000000..977c519677 --- /dev/null +++ b/content/concepts/server/xrpl-servers.md @@ -0,0 +1,3 @@ +# The XRP Ledger Servers + +Placeholder for XRPL servers documentation. \ No newline at end of file diff --git a/content/concepts/tokens/common-misunderstandings-about-freezes.md b/content/concepts/tokens/common-misunderstandings-about-freezes.md new file mode 100644 index 0000000000..0b858c5f2f --- /dev/null +++ b/content/concepts/tokens/common-misunderstandings-about-freezes.md @@ -0,0 +1,26 @@ +# Common Misunderstandings about Freezes + +It is a common misconception that Ripple or others can freeze XRP, similar to how centralized services like PayPal can suspend your account and prevent you from accessing your funds. In reality, while the XRP Ledger does have a [freeze feature](freezing-tokens.md), it can only be used on issued tokens, not on XRP. _No one can freeze XRP.__ + +Tokens in the XRP Ledger are fundamentally different than XRP. Tokens always exist in trust lines, which _can_ be frozen. XRP exists in accounts, which _cannot_ be frozen. + +## Isn't XRP Just Ripple's Token? + +No, XRP is different from tokens. XRP is the only native asset on the XRP Ledger and is required to conduct transactions on the XRP Ledger. XRP has no counterparty, meaning that when someone holds XRP, they are not holding a liability, they are holding the actual currency, XRP. Due to this fact, _XRP cannot be frozen by any entity or individual._ + +## Can Ripple Freeze My Tokens? Or the XRP Ledger Foundation? + +The XRP Ledger is decentralized so that no one party has control over it—not Ripple, not the XRP Ledger Foundation, and not anyone else. + +The _issuer_ of a token can freeze your trust line for _that token specifically_. They can't freeze the rest of your account, or any tokens from different issuers, and they can't stop you from using the XRP Ledger. + +Furthermore, token issuers can voluntarily and permanently _give up_ their ability to freeze tokens. This ["No Freeze"](freezing-tokens.md#no-freeze) setting is intended to allow tokens to behave more like physical cash, in that third parties can't stop you from using it. + + +## But I Heard Ripple Froze Jed McCaleb's XRP? + +This is a misrepresentation of events that actually happened in 2015–2016. Jed McCaleb, a Ripple founder who left the company in 2013, attempted to sell over $1 million US worth of XRP on Bitstamp, a custodial exchange. Ripple representatives argued that this sale would breach an agreement that Jed and Ripple made in 2014. At Ripple's request, [Bitstamp froze Jed's Bitstamp account](https://www.coindesk.com/markets/2015/04/02/1-million-legal-fight-ensnares-ripple-bitstamp-and-jed-mccaleb/) and took the dispute to court. The case was [eventually settled](https://www.coindesk.com/markets/2016/02/12/ripple-settles-1-million-lawsuit-with-former-executive-and-founder/) with both sides declaring they were happy with the outcome. + +Notably, the "freeze" did not happen on the XRP Ledger and did not involve the XRP Ledger's freeze feature. Like any custodial exchange, Bitstamp has the ability to freeze its users' accounts and stop them from trading or withdrawing funds, especially if those funds are involved in a legal dispute. + +In contrast, when trading in the XRP Ledger's decentralized exchange, you custody your own assets so no one can stop you from dealing in XRP. \ No newline at end of file diff --git a/content/concepts/tokens/freezing-tokens.md b/content/concepts/tokens/freezing-tokens.md new file mode 100644 index 0000000000..0961be831b --- /dev/null +++ b/content/concepts/tokens/freezing-tokens.md @@ -0,0 +1,93 @@ +# Freezing Tokens + +Issuers can freeze the tokens they issue in the XRP Ledger. _This does not apply to XRP,__ which is the native asset of the XRP Ledger, not an issued token. + +In certain cases, to meet regulatory requirements, or while investigating suspicious activity, an exchange or gateway may want to freeze token balances. + +**Tip:** No one can freeze XRP in the XRP Ledger. However, custodial exchanges can always freeze the funds they custody at their own discretion. For more details, see [Common Misunderstandings about Freezes](common-misconceptions-about-freezes.md). + +There are three settings related to freezes: + +* [Individual Freeze](#individual-freeze) - Freeze one counterparty. +* [Global Freeze](#global-freeze) - Freeze all counterparties. +* [No Freeze](#no-freeze) - Permanently give up the ability to freeze individual counterparties, as well as the ability to end a global freeze. + +All freeze settings can be enacted regardless of whether the balance(s) to be frozen are positive or negative. Either the token issuer or the currency holder can freeze a trust line; however, the effect is minimal when a currency holder enacts a freeze. + + +## Individual Freeze + +The _Individual Freeze_ feature is a setting on a trust line. When an issuer enables the Individual Freeze setting, the following rules apply to the tokens in that trust line: + +* Payments can still occur directly between the two parties of the frozen trust line. +* The counterparty of that trust line can no longer decrease its balance on the frozen trust line, except in direct payments to the issuer. The counterparty can only send the frozen currencies directly to the issuer. +* The counterparty can still receive payments from others on the frozen trust line. +* The counterparty's offers to sell the tokens in the frozen trust line are considered unfunded. + +Reminder: Trust lines do not hold XRP. XRP cannot be frozen. + +A financial institution can freeze the trust line linking it to a counterparty if that counterparty shows suspicious activity or violates the financial institution's terms of use. The financial institution should also freeze the counterparty in any other systems the financial institution uses that are connected to the XRP Ledger. (Otherwise, an address might still be able to engage in undesired activity by sending payments through the financial institution.) + +An individual address can freeze its trust line to a financial institution. This has no effect on transactions between the institution and other users. It does, however, prevent other accounts, including [operational accounts](../accounts/account-types.md), from sending that financial institution's tokens to the individual account. This type of individual freeze has no effect on offers. + +The Individual Freeze applies to a single trust line. To freeze multiple tokens with a particular counterparty, the address must enable Individual Freeze on the trust lines for each separate currency code. + +An address cannot enable the Individual Freeze setting if it has enabled the [No Freeze](#no-freeze) setting. + + +## Global Freeze + +The _Global Freeze_ feature is a setting on an account. An account can enable a global freeze only on itself. When an issuer enables the Global Freeze feature, the following rules apply to all tokens they issue: + +* All counterparties of the frozen issuer can no longer decrease the balances in their trust lines to the frozen account, except in direct payments to the issuer. (This also affects the issuer's own [operational addresses](../accounts/account-types.md).) +* Counterparties of the frozen issuer can still send and receive payments directly to and from the issuing address. +* All offers to sell tokens issued by the frozen address are considered unfunded. + +Reminder: addresses cannot issue XRP. Global freezes do not apply to XRP. + +It can be useful to enable Global Freeze on a financial institution's [issuing account](../accounts/account-types.md) if the issuer's [secret key](.../accounts/cryptographic-keys.html) is compromised, even after regaining control of a such an address. This stops the flow of funds, preventing attackers from getting away with any more money or at least making it easier to track what happened. Besides enacting a Global Freeze in the XRP Ledger, the issuer should also suspend activities in its outside systems. + +It can also be useful to enable Global Freeze if a financial institution intends to migrate to a new [issuing account](../accounts/account-types.md), or if the financial institution intends to cease doing business. This locks the funds at a specific point in time, so users cannot trade them away for other currencies. + +Global Freeze applies to _all_ tokens issued and held by the address. You cannot enable Global Freeze for only one currency code. If you want to have the ability to freeze some tokens and not others, you should use different addresses for each token. + +An address can always enable the Global Freeze setting. However, if the address has enabled the [No Freeze](#no-freeze) setting, it can never _disable_ Global Freeze. + + +## No Freeze + +The _No Freeze_ feature is a setting on an address that permanently gives up the ability to freeze tokens arbitrarily. An issuer can use this feature to make its tokens as "more like physical money" in the sense that the issuer cannot interfere with counterparties trading the tokens among themselves. + +Reminder: XRP already cannot be frozen. The No Freeze feature only applies to other tokens issued in the XRP Ledger. + +The No Freeze setting has two effects: + +* The issuer can no longer enable Individual Freeze on trust lines to any counterparty. +* The issuer can still enact a Global Freeze, but cannot _disable_ the Global Freeze. + +The XRP Ledger cannot force an issuer to honor the obligations that its issued funds represent, so No Freeze does stop a stablecoin issuer from defaulting on its obligations. However, No Freeze ensures that an issuer does not use the Global Freeze feature unfairly against specific users. + +The No Freeze setting applies to all tokens issued to and from an address. If you want to be able to freeze some tokens but not others, you should use different addresses for each. + +You can only enable the No Freeze setting with a transaction signed by your address's master key secret. You cannot use a Regular Key or a multi-signed transaction to enable No Freeze. + + + diff --git a/content/concepts/tokens/fungible.md b/content/concepts/tokens/fungible.md new file mode 100644 index 0000000000..0583b59daa --- /dev/null +++ b/content/concepts/tokens/fungible.md @@ -0,0 +1,3 @@ +# Fungible Tokens + +Fungible tokens topic placeholder. \ No newline at end of file diff --git a/content/concepts/tokens/non-fungible.md b/content/concepts/tokens/non-fungible.md new file mode 100644 index 0000000000..c81d4b82ab --- /dev/null +++ b/content/concepts/tokens/non-fungible.md @@ -0,0 +1,68 @@ +# Non-fungible Tokens +{% include '_snippets/nfts-disclaimer.md' %} + +The XRP Ledger tokens are, primarily, fungible. + +> Fun·gi·ble /ˈfənjəbəl/ (adj) +> +> 1. able to replace or be replaced by another identical item; mutually interchangeable. + +Fungible tokens can be easily traded between users for XRP or other issued assets on the XRP Ledger's decentralized exchange. This makes them ideal for payments. + + +A good example of a fungible item might be a postage stamp. If you are standing around in 1919 and need to send a letter by airmail, you would purchase a 24-cent stamp and affix it to your envelope. If you lost that stamp, you could use a different 24-cent stamp or use 2 10-cent stamps and 2 2-cent stamps. Very fungible. + +![Jenny Stamps](../../../img/nft-concepts1.png "Jenny Stamps") + +But since you are standing around in 1919, you might be offered 24-cent airmail stamps where the aeroplane on the stamp is accidentally printed upside down. These are the world famous “Inverted Jenny” stamps. Only 100 were circulated on a single sheet of stamps, making them extremely rare and sought after. The current value of each mint condition stamp is appraised at over $1.5 million dollars. + +![Jenny Stamps](../../../img/nft-concepts2.png "Jenny Stamps") + +Those stamps cannot be replaced by just another other 24-cent stamp. They have become _non-fungible_. + +The XRPL Labs team has created a framework that supports non-fungible tokens (NFTs, or “nifties” in the vernacular). Non-fungible tokens serve to encode ownership of unique physical, non-physical, or purely digital goods, such as works of art or in-game items. + + +## NFT Extensions + +Extensions to the XRP Ledger support two new objects and a new ledger structure. + +The `NFToken` is a native NFT type. It has operations to enumerate, purchase, sell, and hold such tokens. An `NFToken` is a unique, indivisible unit that is not used for payments. + +The `NFTokenPage object` contains a set of `NFToken` objects owned by the same account. + +You create a new `NFToken` using the `NFTokenMint` transaction. + +`NFTokenOffer` object is a new object that describes an offer to buy or sell a single `NFToken`. + +You destroy an `NFToken` using the `NFTokenBurn` transaction. + + +## `NFToken` Lifecycle + +You create a NFT using the `NFTokenMint` transaction. The `NFToken` lives on the `NFTokenPage` of the issuing account. You can create an `NFTokenOffer` to sell the `NFToken`, creating an entry to the XRP Ledger. Another account can accept the `NFTokenOffer`, transferring the `NFToken` to the accepting account’s `NFTokenPage`. If the `lsfTransferable `flag is set to _true_ (0x000008) when the `NFToken` is minted, the `NFToken` can be traded multiple times between accounts. The `NFToken` can be permanently destroyed by its owner using the `NFTokenBurn` transaction. + +![The NFT Lifecycle](../../../img/nft-lifecycle.png "NFT Lifecycle Image") + + + \ No newline at end of file diff --git a/content/concepts/tokens/token-types.md b/content/concepts/tokens/token-types.md new file mode 100644 index 0000000000..800cb605a0 --- /dev/null +++ b/content/concepts/tokens/token-types.md @@ -0,0 +1,31 @@ +# Token Types + +You can use tokens for a variety of purposes on the XRP Ledger. + +## Stablecoins + +A common model for tokens in the XRP Ledger is that an issuer holds assets of equivalent value outside of the XRP Ledger, and issues tokens representing that value on the ledger. This type of issuer is sometimes called a _gateway_ because currency can move into and out of the XRP Ledger through their service. If the assets that back a token use the same amounts and denomination as the tokens in the ledger, that token can be considered a "stablecoin" because—in theory—the exchange rate between that token and its off-ledger representation should be stable at 1:1. + +A stablecoin issuer should offer _deposits_ and _withdrawals_ to exchange the tokens for the actual currency or asset in the world outside the XRP Ledger. + +In practice, the XRP Ledger is a computer system that cannot enforce any rules outside of itself, so stablecoins on the XRP Ledger depend on their issuer's integrity. If you can't count on the stablecoin's issuer to redeem your tokens for the real thing on demand, then you shouldn't expect the stablecoin to retain its value. As a user, you should be mindful of who's issuing the tokens: are they reliable, lawful, and solvent? If not, it's probably best not to hold those tokens. + +For more information on how to run a gateway, see Becoming an XRP Ledger Gateway. + + +## Community Credit + +Another way you can use the XRP Ledger is for "community credit", a system where individuals who know each other can use the XRP Ledger to track who owes who else how much money. A powerful feature of the XRP Ledger is that it can automatically and atomically use these debts to settle payments through rippling. + +For example, if Asheesh owes Marcus $20, and Marcus owes Bharath $50, Bharath can "pay" Asheesh $20 by canceling that much of Marcus's debt to him in exchange for canceling Asheesh's debt to Marcus. The reverse is also possible: Asheesh can pays Bharath through Marcus by increasing their respective debts. The XRP Ledger can settle complex chains of exchanges like this in a single transaction without the accounts in the middle needing to do anything manually. + +For more on this type of usage, see paths. + + +## Other Tokens + +There are other use cases for tokens issued in the XRP Ledger. For example, you can create an "Initial Coin Offering" (ICO) by issuing a fixed amount of currency to a secondary address, then "throwing away the key" to the issuer. + +**Warning:** ICOs may be [regulated as securities](https://www.sec.gov/oiea/investor-alerts-and-bulletins/ib_coinofferings) in the USA. + +Be sure to research the relevant regulations before engaging in any financial service business. diff --git a/content/concepts/transactions/about-canceling-a-transaction.md b/content/concepts/transactions/about-canceling-a-transaction.md new file mode 100644 index 0000000000..8fccc88408 --- /dev/null +++ b/content/concepts/transactions/about-canceling-a-transaction.md @@ -0,0 +1,24 @@ +--- +html: about-canceling-a-transaction.html +parent: transactions.html +blurb: Before a transaction is final it might be possible to cancel it using a separate transaction. +labels: + - Transactions +--- +# About Canceling a Transaction + +An important and intentional feature of the XRP Ledger is that a [transaction](transactions.md)'s outcome is [final](finality-of-results.md) as soon as it has been incorporated in a [ledger version](../xrpl/ledgers.md) that is validated by the [consensus process](../xrpl/consensus.md). + +If a transaction has _not_ yet been included in a validated ledger, it might be possible to effectively cancel it by sending another transaction from the same sending address with the same `Sequence` value. If you do not want the replacement transaction to do anything, send an `AccountSet` transaction with no options. + +**Caution:** There is no guaranteed way to cancel a valid transaction after it has been distributed to the network. The process described here might or might not work, depending on factors including how busy the network is, the network topology, and the [transaction cost](transaction-cost.md) of the proposed transaction. + + + +If the transaction has already been distributed to the network and proposed as a [candidate transaction](../xrpl/consensus.md#consensus-1) in servers' consensus proposals, it might be too late to cancel. It is more likely that you can successfully cancel a transaction that is [queued](../server/transaction-queue.md) or is stuck "in limbo" because its [transaction cost](transaction-cost.md) is not high enough to meet the network's current requirements. In this case, the replacement transaction can either do nothing, or do the same thing as the transaction to be canceled. The replacement transaction is more likely to succeed if its transaction cost is higher. + +For example, if you try to submit 3 transactions with sequence numbers 11, 12, and 13, but transaction 11 gets lost somehow or does not have a high enough [transaction cost](transaction-cost.md) to be propagated to the network, then you can cancel transaction 11 by submitting an AccountSet transaction with no options and sequence number 11. This does nothing (except destroying the transaction cost for the new transaction 11), but it allows transactions 12 and 13 to become valid. + +This approach is preferable to renumbering and resubmitting transactions 12 and 13, because it prevents transactions from being effectively duplicated under different sequence numbers. + +In this way, an AccountSet transaction with no options is the canonical "[no-op](http://en.wikipedia.org/wiki/NOP)" transaction. diff --git a/content/concepts/transactions/finality-of-results.md b/content/concepts/transactions/finality-of-results.md new file mode 100644 index 0000000000..e4bbf9a885 --- /dev/null +++ b/content/concepts/transactions/finality-of-results.md @@ -0,0 +1,65 @@ +--- +html: finality-of-results.html +parent: transactions.html +blurb: Transaction order is not final until the ledger is closed. +labels: + - Transactions +--- +# Finality of Results + +The order in which transactions apply to the consensus [ledger](../xrpl/ledgers.md) is not final until a ledger is closed and the exact transaction set is approved by the [consensus process](../xrpl/consensus.md). A transaction that succeeded initially could still fail, and a transaction that failed initially could still succeed. Additionally, a transaction that was rejected by the consensus process in one round could achieve consensus in a later round. + +A validated ledger can include successful transactions (`tes` result codes) as well as failed transactions (`tec` result codes). No transaction with any other result is included in a ledger. + +For any other result code, it can be difficult to determine if the result is final. The following table summarizes when a transaction's outcome is final, based on the result code from submitting the transaction: + +| Result Code | Finality | +|:----------------|:-----------------------------------------------------------| +| `tesSUCCESS` | Final when included in a validated ledger | +| Any `tec` code | Final when included in a validated ledger | +| Any `tem` code | Final unless the protocol changes to make the transaction valid | +| `tefPAST_SEQ` | Final when another transaction with the same sequence number is included in a validated ledger | +| `tefMAX_LEDGER` | Final when a validated ledger has a ledger index higher than the transaction's `LastLedgerSequence` field, and no validated ledger includes the transaction | + +Any other transaction result is potentially not final. In that case, the transaction could still succeed or fail later, especially if conditions change such that the transaction is no longer prevented from applying. For example, trying to send a non-XRP currency to an account that does not exist yet would fail, but it could succeed if another transaction sends enough XRP to create the destination account. A server might even store a temporarily-failed, signed transaction and then successfully apply it later without asking first. + +## How can non-final results change? + +When you initially submit a transaction, the `rippled` server tentatively applies that transaction to its current open ledger, then returns the tentative [transaction results](../transactions/transaction-results/transaction-results.md) from doing so. However, the transaction's final result might be very different than its tentative results, for several reasons: + +- The transaction might be delayed until a later ledger version, or might never be included in a validated ledger. For the most part, the XRP Ledger follows a principle that all valid transactions should be processed as soon as possible. However, there are exceptions, including: + + - If a proposed transaction has not been relayed to a majority of validators by the time a [consensus round](../xrpl/consensus.md) begins, it might be postponed until the next ledger version, to give the remaining validators time to fetch the transaction and confirm that it is valid. + + - If an address sends two different transactions using the same sequence number, at most one of those transactions can become validated. If those transactions are relayed through the network in different paths, a tentatively-successful transaction that some servers saw first might end up failing because the other, conflicting transaction reached a majority of servers first. + + - To protect the network from spam, all transactions must destroy a [transaction cost](transaction-cost.md) in XRP to be relayed throughout the XRP Ledger peer-to-peer network. If heavy load on the peer-to-peer network causes the transaction cost to increase, a transaction that tentatively succeeded might not get relayed to enough servers to achieve a consensus, or might be [queued](../server/transaction-queue.md) for later. + + - Temporary internet outages or delays might prevent a proposed transaction from being successfully relayed before the transaction's intended expiration, as set by the `LastLedgerSequence` field. (If the transaction does not have an expiration, then it remains valid and could succeed any amount of time later, which can be undesirable in its own way. + + + + - Combinations of two or more of these factors can also occur. + +- The [order transactions apply in a closed ledger](../xrpl/ledgers.md#open-closed-and-validated-ledgers) is usually different than the order those transactions were tentatively applied to a current open ledger; depending on the transactions involved, this can cause a tentatively-successful transaction to fail or a tentatively-failed transaction to succeed. Some examples include: + + - If two transactions would each fully consume the same offer] in the decentralized exchange, whichever one comes first succeeds, and the other fails. Since the order in which those transactions apply might change, the one that succeeded can fail and the one that failed can succeed. Since offers can be partially executed, they could also still succeed, but to a greater or lesser extent. + + + + + - If a [cross-currency payment](./payments/cross-currency-payments.md) succeeds by consuming an decentralized exchange, but a different transaction consumes or creates offers in the same order book, the cross-currency payment might succeed with a different exchange rate than it had when it executed tentatively. If it was a [partial payment](./payments/partial-payments.md), it could also deliver a different amount. + + - A `Payment` transaction that tentatively failed because the sender did not have enough funds might later succeed because another transaction delivering the necessary funds came first in the canonical order. The reverse is also possible: a transaction that tentatively succeeded might fail because a transaction delivering the necessary funds did not come first after being put into canonical order. + + **Tip:** For this reason, when running tests against the XRP Ledger, be sure to wait for a ledger close in between transactions if you have several accounts affecting the same data. If you are testing against a server in stand-alone mode, you must manually close the ledger in such cases. + + + + \ No newline at end of file diff --git a/content/concepts/transactions/multi-signing.md b/content/concepts/transactions/multi-signing.md new file mode 100644 index 0000000000..b42d43422d --- /dev/null +++ b/content/concepts/transactions/multi-signing.md @@ -0,0 +1,86 @@ +--- +html: multi-signing.html +parent: transactions.html +blurb: In some cases, transactions might require approval from more than one account for authorization. +labels: + - Transactions +--- +# Multi-Signing + +Multi-signing in the XRP Ledger is a method of [authorizing transactions](transactions.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](../accounts/cryptographic-keys.md#master-key-pair), and a [regular key pair](../accounts/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. +* ... and more. + +## SignerLists + +Before you can multi-sign, you must create a list of which addresses can sign for you. + +The `SignerListSet` transaction defines which addresses can authorize transactions from your address. You can include 1 to 8 addresses in a SignerList. The SignerList cannot include the sender's address and there can be no duplicate entries. You can control how many signatures are needed, in which combinations, by using the *SignerWeight* and *SignerQuorum* values of the SignerList. + +If the `ExpandedSignerList` amendment :not_enabled: is enabled, you can include 1 to 32 addresses in a SignerList. + +### Signer Weight + +You can assign a weight to each signer in the SignerList. The weight represents the relative authority of the signer to other signers on the list. The higher the value, the more authorization authority. Individual weight values cannot exceed 216-1. + +### Signer Quorum + +The quorum value 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 SignerList: meaning, it must be possible to achieve a quorum with the given signer weights. + +### Wallet Locator + +If the `ExpandedSignerList` amendment :not_enabled: is enabled, 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. + +### Examples Using Signer Weight and Signer Quorum + +The weight 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 typical use case, you might have a shared account 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.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 SignerList 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 in the ledger.* The transaction must include the `SigningPubKey` field as an empty string. +* The transaction must include a `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](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 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.) + + \ No newline at end of file diff --git a/content/concepts/transactions/payments/checks.md b/content/concepts/transactions/payments/checks.md new file mode 100644 index 0000000000..8ac2ebe9a5 --- /dev/null +++ b/content/concepts/transactions/payments/checks.md @@ -0,0 +1,115 @@ +--- +html: checks.html +parent: payments.html +blurb: Checks can be used for deferred payments that can be canceled or cashed by recipients. +labels: + - Transactions +--- +# Checks + +_(Added by the Checks amendment.)_ + +The Checks feature in the XRP Ledger allows users to create deferred payments that can be canceled or cashed by the intended recipients. Like personal paper checks, XRP Ledger Checks start with the sender of the funds creating a Check that specifies an amount and a recipient. The recipient cashes the check to pull the funds from the sender's account into the recipient's account. No money moves until the recipient cashes the Check. Because funds are not put on hold when the Check is created, cashing a Check can fail if the sender doesn't have enough funds when the recipient tries to cash it. If there's a failure cashing the check, the check's recipient can retry until the Check expires. + +XRP Ledger Checks may have expiration times after which they may no longer be cashed. If the recipient doesn't successfully cash the Check before it expires, the Check can no longer be cashed, but the object remains in the XRP Ledger until someone cancels it. Anyone may cancel the Check after it expires. Only the sender and recipient can cancel the Check before it expires. The Check object is removed from the Ledger when the sender successfully cashes the check or someone cancels it. + +Checks have some similarities to [escrow](escrow.md) and [payment channels](payment-channels.md), but there are some important differences between those features and checks: + +* You can send [tokens](../../tokens/tokens.md) with checks. With payment channels and Escrow, you can only send XRP. + +* Checks do not lock up or set aside any funds. The XRP involved in payment channels and escrow cannot be spent until it is redeemed with a claim provided by the sender (payment channels), or released by an expiration or crypto-condition (escrow). + +* You can send XRP to yourself through escrow. You cannot send checks to yourself. + + +**Note:** The Checks amendment changes the expiration behavior of the `OfferCreate` transaction. + + + + +## Why Checks? + +Traditional paper checks allow people to transfer funds without immediately exchanging physical currency. XRP Ledger Checks allow people to exchange funds asynchronously using a process that is familiar to and accepted by the banking industry. + +XRP Ledger Checks also solve a problem that is unique to the XRP Ledger: they allow users to reject unwanted payments or accept only part of a payment. This is useful for institutions that need to be careful about accepting payments for compliance reasons. + + +### Use Case: Payment Authorization + +**Problem:** To comply with regulations like BSA, KYC, AML, and CFT, financial institutions must provide documentation about the source of funds they receive. Such regulations seek to prevent the illicit transfer of funds by requiring institutions to know the source and destination of all payments processed by the institution. Because of the nature of the XRP Ledger, anyone could potentially send XRP (and, under the right circumstances, tokens) to an institution's account on the XRP Ledger. Dealing with such unwanted payments adds significant cost and time delays to these institutions' compliance departments, including potential fines or penalties. + + + +**Solution:** Institutions can enable deposit authorization on their XRP Ledger accounts by setting the `asfDepositAuth` flag in an `AccountSet` transaction. This makes the account unable to receive Payment transactions. Accounts with Deposit Authorization enabled can only receive funds through Escrow, Payment Channels, or Checks. Checks are the most straightforward, familiar, and flexible way to transfer funds if Deposit Authorization is enabled. + + +## Usage + +Checks typically have the lifecycle described below. + + + +[![Check flow diagram (successful cashing)](../../../../img/checks-happy-path.png)](../../../../img/checks-happy-path.png) + +**Step 1:** To create a Check, the sender submits a `CheckCreate` transaction and specifies the recipient (`Destination`), expiration time (`Expiration`), and maximum amount that may be debited from the sender's account (`SendMax`). + + +**Step 2:** After the CheckCreate transaction is processed, a Check object is created on the XRP Ledger. This object contains the properties of the check as defined by the transaction that created it. The object can only be modified by the sender (by canceling it with a `CheckCancel` transaction) or recipient (by canceling it or cashing it) before the expiration time passes. After the expiration time, anyone may cancel the Check. + +**Step 3:** To cash the check, the recipient submits a `CheckCash` transaction. The recipient has two options for cashing the check: + +* `Amount` — The recipient can use this option to specify an exact amount to cash. This may be useful for cases where the sender has padded the check to cover possible [transfer fees](../../tokens/transfer-fees.md) and the recipient wants to accept the exact amount on an invoice or other contract. + +* `DeliverMin` — The recipient can use this option to specify the minimum amount they are willing to receive from the Check. If the recipient uses this option, the XRP Ledger attempts to deliver as much as possible and always delivers at least this amount. The transaction fails if the amount that can be credited to the recipient is not at least the requested amount. + +If the sender has enough funds to cover the Check and the expiration time has not passed, the funds are debited from the sender's account and credited to the recipient's account, and the Check object is destroyed. + + + +#### Expiration Case + +In the case of expirations, Checks have the lifecycle described below. + + + +[![Check flow diagram (expiration)](../../../../img/checks-expiration.png)](../../../../img/checks-expiration.png) + + +All Checks start the same way, so **Steps 1 and 2** are the same. + +**Step 3a:** If the Check expires before the recipient can cash it, the Check can no longer be cashed but the object remains in the ledger. + +**Step 4a:** After a Check expires, anyone may cancel it by submitting a [CheckCancel][] transaction. That transaction removes the Check from the ledger. + + + + +## Availability of Checks + +The Checks amendment became enabled on the XRP Ledger Mainnet on 2020-06-18. For more information about how amendments are enabled and voted on, see [Amendment Process](../../../../amendments/amendments.md#amendment-process). + +To check the status of an amendment on a test network or private network, use the `feature` method. + + \ No newline at end of file diff --git a/content/concepts/transactions/payments/cross-currency-payments.md b/content/concepts/transactions/payments/cross-currency-payments.md new file mode 100644 index 0000000000..93fef994ba --- /dev/null +++ b/content/concepts/transactions/payments/cross-currency-payments.md @@ -0,0 +1,41 @@ +--- +html: cross-currency-payments.html +parent: payments.html +blurb: In the XRP Ledger, you can send cross-currency payments that exchange tokens, XRP, or both. +labels: + - Transactions +--- +# Cross-Currency Payments + +In the XRP Ledger, you can send cross-currency payments that exchange tokens, XRP, or both. Like [direct XRP payments](direct-xrp-payments.html), these payments use the `Payment transaction` type. Cross-currency payments within the XRP Ledger are fully atomic, meaning that either the payment fully executes or no part of it executes. + +By default, cross-currency payments deliver a fixed amount to their destination at a variable cost to their source. Cross-currency payments can also be [partial payments](partial-payments.md), which deliver a variable amount to the destination within a fixed sending limit. + + +## Prerequisites + +- By definition, a cross-currency payment involves at least two currencies, which means that at least one currency involved must be a non-XRP [token](../../tokens/tokens.md). +- There must be at least one [path](../../tokens/paths.md) between the sender and receiver, and the total liquidity across all paths must be enough to execute the payment. Cross-currency payments convert from one currency to another by consuming offers in the XRP Ledger's decentralized exchange. + + + + +## Auto-Bridging + +Cross-currency payments that exchange one token for another token can automatically use XRP to bridge the tokens, when it decreases the cost of the payment. For example, a payment sending from USD to MXN automatically converts USD to XRP and then XRP to MXN if doing so is cheaper than converting USD to MXN directly. Larger trades can use a combination of direct (USD-MXN) and auto-bridged (USD-XRP-MXN) conversions. + + \ No newline at end of file diff --git a/content/concepts/transactions/payments/direct-xrp-payments.md b/content/concepts/transactions/payments/direct-xrp-payments.md new file mode 100644 index 0000000000..e088fa39f5 --- /dev/null +++ b/content/concepts/transactions/payments/direct-xrp-payments.md @@ -0,0 +1,92 @@ +--- +html: direct-xrp-payments.html +parent: payments.html +blurb: Direct XRP payments are the quintessential type of payment for the XRPL. +labels: + - Transactions +--- +# Direct XRP Payments + +The basis of any financial system is _transferring value_: or, in one word, payments. The quintessential type of payment in the XRP Ledger is a direct XRP-to-XRP payment, which transfers XRP directly from one account in the XRP Ledger to another. + +## About Direct XRP-to-XRP Payments + +Generally, any address in the XRP Ledger can send XRP directly to any other address. The address on the receiving side is often called the _destination address_, and the address on the sending side is called the _source address_. To send XRP directly, the sender uses a `Payment` transaction, which can be as concise as the following: + +```json +{ + "TransactionType": "Payment", + "Account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", + "Destination": "ra5nK24KXen9AHvsdFTKHSANinZseWnPcX", + "Amount": "13000000" +} +``` + +These transaction instructions mean: Send a payment from `rf1Bi...` to `ra5nK...` delivering exactly 13 XRP. If the transaction is successfully processed, it does exactly that. Since it usually takes about 4 seconds for each new ledger version to become [validated](../../xrpl/consensus.md), a successful transaction can be created, submitted, executed, and have a final outcome in 8 seconds or less, even if gets queued for the ledger version after the current in-progress one. + +**Caution:** The `Payment` transaction type can also be used for some more specialized kinds of payments, including [cross-currency payments](cross-currency-payments.md) and [partial payments](partial-payments.md). In the case of partial payments, it is possible that the `Amount` shows a large amount of XRP even if the transaction only delivered a very small amount. See [partial payments exploit](partial-payments.md#partial-payments-exploit) for how to avoid crediting a customer for the wrong amount. + +Direct XRP-to-XRP payments cannot be partial payments, but partial payments can deliver XRP after converting from a different source currency. + + +## Funding Accounts + +Any mathematically-valid address can receive a payment, even if the XRP Ledger has no record of that address existing beforehand, as long as the payment delivers enough XRP to meet the minimum [account reserve](../../accounts/reserves.md). If the payment would not deliver enough XRP, it fails. + +For more information, see [Accounts](../../accounts/accounts.md#creating-accounts). + + +## Address Reuse + +In the XRP Ledger, addresses where you can receive payments are permanent, and have a non-trivial [reserve requirement](../../accounts/reserves.md) of XRP that they cannot spend. This means that, contrary to some other blockchain systems, it is not a good idea to use a different, disposable address for every transaction. The best practice for the XRP Ledger is to reuse the same address for multiple transactions. If you use the address regularly (especially if it's managed by an internet-connected service), you should set a [regular key](../../accounts/cryptographic-keys.md) and proactively change keys on a regular basis to reduce the risk of a key compromise. + +As a sender, it is best not to assume that your intended recipient is using the same address from the last time you sent them a payment. Inevitably, sometimes security compromises happen and a person or business has to change addresses. Before sending money, you should ask the recipient for their current receiving address, so you don't accidentally send money to a malicious user who has taken control of a compromised old address. + + +## How Direct XRP Payments Are Processed + +From a relatively high level, the XRP Ledger's transaction processing engine applies a direct XRP payment as follows: + +1. It validates the parameters of the `Payment` transaction. If the transaction is structured to send and deliver XRP, the transaction processing engine recognizes it as a direct XRP-to-XRP payment. Validation checks include: + + - Checking that all fields are formatted correctly. For example, for direct XRP payments, the `Amount` field must be drops of XRP. + - Checking that the sending address is a funded [account](../../accounts/accounts.md) in the XRP Ledger. + - Checking that all provided signatures are valid for the sending address. + - Confirming that the destination address is different than the sender address. (It is not sufficient to send to the same address with a different [destination tag](../source-and-destination-tags.md).) + - Confirming that the sender has a high enough XRP balance to send the payment. + + If any check fails, the payment fails. + +2. It checks whether the receiving address is a funded account. + + - If the receiving address is funded, the engine checks any additional requirements for receiving payments, such as [Deposit Authorization](../../accounts/deposit-authorization.md) or [`RequireDest`](../source-and-destination-tags.md#requiring-tags). If the payment does not satisfy any of these additional requirements, the payment fails. + - If the receiving address is not funded, it checks whether the payment would deliver enough XRP to meet the minimum [account reserve](../../accounts/reserves.md). If not, the payment fails. + +3. It debits the sending account by an amount of XRP specified by the `Amount` field plus the XRP to be destroyed for the [transaction cost](../transaction-cost.md) and credits the receiving account for the same amount. + + If necessary, it creates a new account (`AccountRoot` object) for the receiving address. The new account's starting balance is equal to the `Amount` of the payment. + + The engine adds a `delivered_amount` field to the [transaction's metadata](../transaction-metadata.md) to indicate how much was delivered. You should always use `delivered_amount`, **not** the `Amount` field, to avoid being tricked about how much XRP you received. (Cross-currency "Partial Payments" can deliver less XRP than stated in the `Amount` field.) For more information, see [Partial Payments](partial-payments.md). + + +## Comparison to Other Payment Types + +- **Direct XRP Payments** are the only way to both send and receive XRP in a single transaction. They are a good balance of speed, simplicity, and low cost. +- [Cross-currency payments](cross-currency-payments.md) also use the `Payment` transaction type, but can send any combination of XRP and non-XRP [tokens](../../tokens/tokens.md) except XRP-to-XRP. They can also be [partial payments](partial-payments.md). Cross-currency payments are good for payments not denominated in XRP or for taking arbitrage opportunities in the decentralized exchange. +- [Checks](checks.md) let the sender set up an obligation without transferring any money immediately. The recipient can cash it any time before it expires, but the amount is not guaranteed. Checks can send either XRP or [tokens](../../tokens/tokens.md). Checks are good for giving the recipient the autonomy to claim the payment. +- [Escrow](escrow.md) sets aside XRP which can be claimed by its intended recipient when certain conditions are met. The XRP amount is fully guaranteed and cannot be otherwise used by the sender unless the Escrow expires. Escrow is good for smart contracts in large amounts. +- [Payment Channels](payment-channels.md) set aside XRP. The recipient can claim XRP from the channel in bulk using signed authorizations. Individual authorizations can be verified without sending a full XRP Ledger transaction. Payment channels are good for extremely high-volume micropayments or "streaming" payments. + + \ No newline at end of file diff --git a/content/concepts/transactions/payments/escrow.md b/content/concepts/transactions/payments/escrow.md new file mode 100644 index 0000000000..72721845ea --- /dev/null +++ b/content/concepts/transactions/payments/escrow.md @@ -0,0 +1,152 @@ +--- +html: escrow.html +parent: payments.html +blurb: Escrow holds funds and delivers them when specified criteria are fulfilled. +labels: + - Transactions +--- +# Escrow + +Escrow is a feature of the XRP Ledger that allows you to send conditional XRP payments. These conditional payments, called _escrows_, set aside XRP and deliver it later when certain conditions are met. Conditions to successfully finish an escrow include time-based unlocks and `crypto-conditions`. Escrows can also be set to expire if not finished in time. + +The XRP set aside in an escrow is locked up. No one can use or destroy the XRP until the escrow has been successfully finished or canceled. Before the expiration time, only the intended receiver can get the XRP. After the expiration time, the XRP can only be returned to the sender. + +## Usage + + + +[![Escrow Flow Diagram (Successful finish)](../../../../img/escrow-success-flow.png)](../../../../img/escrow-success-flow.png) + +**Step 1:** To send an escrow, the sender uses an `EscrowCreate` transaction to lock up some XRP. This transaction defines a finish time, an expiration time, or both. The transaction may also define a crypto-condition that must be fulfilled to finish the escrow. This transaction must define an intended recipient for the XRP; the recipient _might_ be the same as the sender. + +**Step 2:** After this transaction has been processed, the XRP Ledger has an Escrow object that holds the escrowed XRP. This object contains the properties of the escrow as defined by the transaction that created it. If this escrow has a finish time, no one can access the XRP before then. + +**Step 3:** The recipient, or any other XRP Ledger address, sends an `EscrowFinish` transaction to deliver the XRP. If the correct conditions are met, this destroys the Escrow object in the ledger and credits the XRP to the intended recipient. If the escrow has a crypto-condition, this transaction must include a fulfillment for that condition. If the escrow has an expiration time that has already passed, the EscrowFinish transaction instead fails with the code [`tecNO_PERMISSION`](../transaction-results/tec-codes.html). + +### Expiration Case + +[![Escrow Flow Diagram (Expired escrow)](../../../../img/escrow-cancel-flow.png)](../../../../img/escrow-cancel-flow.png) + +All escrows start the same way, so **Steps 1 and 2** are the same as in the successful case. + +**Step 3a:** If the escrow has an expiration time, and it has not been successfully finished before then, the escrow is considered expired. It continues to exist in the XRP Ledger, but can no longer successfully finish. (Expired objects remain in the ledger until a transaction modifies them. Time-based triggers cannot change the ledger contents.) + +**Step 4a:** The sender, or any other XRP Ledger address, sends an `EscrowCancel` transaction to cancel the expired escrow. This destroys the Escrow object in the ledger and returns the XRP to the sender. + + + + +## Limitations + +Escrow is designed as a feature to enable the XRP Ledger to be used in the `Interledger Protocol` and with other smart contracts. The current version has a modest scope to avoid complexity. + +- Escrow only works with XRP, not tokens. +- Escrow requires sending at least two transactions: one to create the escrow, and one to finish or cancel it. Thus, it may not be financially sensible to escrow payments for very small amounts, because the participants must destroy the [transaction cost](../transaction-cost.md) of the two transactions. + - When using Crypto-Conditions, the [cost of the transaction to finish the escrow](#escrowfinish-transaction-cost) is higher than usual. +- All escrows must be created with a "finish-after" time or a `crypto-condition`, or both. If the escrow does not have a finish-after time, it must have an expiration time. + + **Note:** The _fix1571 amendment_ changed the requirements for creating an escrow. Escrows created before that amendment could provide an expiration time with no condition or finish-after time. Anyone can finish such escrows immediately (sending the funds to the intended recipient). + +- None of the time values can be in the past when the escrow-creating transaction executes. +- Timed releases and expirations are limited to the resolution of XRP Ledger closes. This means that, in practice, times may be rounded to approximately 5 second intervals, depending on exactly when the ledgers close. +- The only supported `crypto-condition` type is PREIMAGE-SHA-256. + +Escrow provides strong guarantees that are best suited for high-value, low-quantity payments. [Payment Channels](payment-channels.md) are better suited for fast, low-value payments. Of course, unconditional payments are also preferable for many use cases. + +## State Diagram + +The following diagram shows the states an Escrow can progress through: + +[![State diagram showing escrows going from Held → Ready/Conditionally Ready → Expired](../../../../img/escrow-states.png)](../../../../img/escrow-states.png) + +The diagram shows three different cases for three possible combinations of the escrow's "finish-after" time (`FinishAfter` field), crypto-condition (`Condition` field), and expiration time (`CancelAfter` field): + +- **Time-based Escrow (left):** With only a finish-after time, the escrow is created in the **Held** state. After the specified time has passed, it becomes **Ready** and anyone can finish it. If the escrow has an expiration time and no one finishes it before that time passes, then the escrow becomes **Expired**. In the expired state, an escrow cannot be finished, and anyone can cancel it. If the escrow does not have a `CancelAfter` field, it never expires and cannot be canceled. + +- **Combination Escrow (center):** If the escrow specifies both a crypto-condition (`Condition` field) _and_ a "finish-after" time (`FinishAfter` field), the escrow is **Held** until its finish-after time has passed. Then it becomes **Conditionally Ready**, and can finish it if they supply the correct fulfillment to the crypto-condition. If the escrow has an expiration time (`CancelAfter` field), and no one finishes it before that time passes, then the escrow becomes **Expired**. In the expired state, an escrow cannot be finished, and anyone can cancel it. If the escrow does not have a `CancelAfter` field, it never expires and cannot be canceled. + +- **Conditional Escrow (right):** If the escrow specifies a crypto-condition (`Condition` field) and not a finish-after time, the escrow becomes **Conditionally Ready** immediately when it is created. During this time, anyone can finish the escrow, but only if they supply the correct fulfillment to the crypto-condition. If no one finishes the escrow before its expiration time (`CancelAfter` field), the escrow becomes **Expired**. (An escrow without a finish-after time _must_ have an expiration time.) In the expired state, the escrow can no longer be finished, and anyone can cancel it. + + + +## Availability of Escrow + +Conditional payments have been enabled by the ["Escrow" Amendment](../../../../amendments/known-amendments.md#escrow) to the XRP Ledger Consensus Protocol since 2017-03-31. A previous version of the same functionality was available on the XRP Ledger Test Net by the name "Suspended Payments" (SusPay) in 2016. + +When testing in stand-alone mode, you can force the Escrow feature to be enabled locally regardless of the amendment status. Add the following stanza to your `rippled.cfg`: + + [features] + Escrow + +You can check the status of the Escrow amendment using the `feature` method. + +## EscrowFinish Transaction Cost + +When using `crypto-conditions`, the EscrowFinish transaction must pay a [higher transaction cost](../transaction-cost.md#special-transaction-costs) because of the higher processing load involved in verifying the crypto-condition fulfillment. + +If the escrow is purely time-locked with no crypto-condition, the EscrowFinish costs only the standard [transaction cost](../transaction-cost.html) for a reference transaction. + +The additional transaction cost required is proportional to the size of the fulfillment. Currently, an EscrowFinish with a fulfillment requires a minimum transaction cost of **330 drops of XRP plus 10 drops per 16 bytes in the size of the fulfillment**. If the transaction is [multi-signed](../multi-signing.md), the cost of multi-signing is added to the cost of the fulfillment. + + + +**Note:** The above formula is based on the assumption that the reference cost of a transaction is 10 drops of XRP. + +If [Fee Voting](../../../xrpl/fee-voting.html) changes the `reference_fee` value, the formula scales based on the new reference cost. The generalized formula for an EscrowFinish transaction with a fulfillment is as follows: + +``` +reference_fee * (signer_count + 33 + (fulfillment_bytes / 16)) +``` + + +## Why Escrow? + +The age-old practice of [Escrow](https://en.wikipedia.org/wiki/Escrow) enables many kinds of financial transactions that would be considered risky otherwise, especially online. By letting a trusted third party hold the money while a transaction or evaluation period is underway, both sides can be assured that the other must hold up their end of the bargain. + +The Escrow feature takes this idea further by replacing the third party with an automated system built into the XRP Ledger, so that the lock up and release of funds is impartial and can be automated. + +Fully automated escrow, backed by the integrity of the XRP Ledger itself, solves important problems for Ripple, and we think there are many other use cases that escrow enables. Ripple encourages the industry to find new and unique ways to put escrow to use. + +### Use Case: Time-based Lock-Up + +**Background:** Ripple holds a large amount of the total XRP, which it sells methodically as a way to fund and incentivize the healthy development of the XRP Ledger and related technologies. At the same time, owning such a large chunk of XRP causes problems for the company, such as: + +- Individuals and businesses who use the XRP Ledger worry that their investments in XRP could be diluted or devalued if Ripple were to flood the market by selling at a higher rate than usual. + - Although flooding the market would be a long-term loss for Ripple, the possibility that the company could do so exerts downward pressure over the price of XRP, and thus decreases the value of the company's assets. +- Ripple must carefully manage ownership of its accounts to protect against digital theft and other forms of malicious behavior, even by insiders. + +**Solution:** By placing 55 billion XRP into time-based escrows, Ripple ensures that the supply of XRP in circulation is predictable and increases at a slow but steady rate. Others who hold XRP know that Ripple cannot flood the market, even if the company's priorities or strategy changes. + +Placing the money into escrow does not directly protect Ripple's holdings from malicious actors, but it sharply reduces the amount of XRP that can be quickly stolen or redirected if a malicious actor gains temporary control over Ripple's XRP accounts. This reduces the risk of catastrophic losses of XRP and increases the time for Ripple to detect, prevent, and track down unintended uses of Ripple's XRP assets. + +### Use Case: Interledger Payments + +**Background:** In the quickly-developing world of financial technology, one of the core challenges is coordinating activities that cross multiple digital money systems, or ledgers. Many proposed solutions to this problem (including early views of the XRP Ledger!) can be reduced to creating "one ledger to rule them all." Ripple believes no single system can meet the needs of everyone in the world: in fact, some desirable features are mutually exclusive. Instead, Ripple believes that an interconnected network of ledgers—an _interledger_—is the true future of financial technology. The `Interledger Protocol` defines standards for making as many systems as possible connect securely and smoothly. + +The most fundamental principle of inter-ledger payments is _conditional transfers_. Multi-hop payments have a risk problem: the more hops in the middle, the more places the payment can fail. Interledger solves this with the financial equivalent of a "[two-phase commit](https://en.wikipedia.org/wiki/Two-phase_commit_protocol)", where the two steps are (1) prepare conditional transfers, then (2) fulfill the conditions to execute the transfers. The Interledger project defined a `crypto-conditions` specification to standardize automated ways to define and verify conditions, and settled on SHA-256 hashes as a "common denominator" of such conditions. + +**Solution:** The Escrow feature makes the XRP Ledger ideal for bridging multi-hop payments using the Interledger Protocol, because it natively supports transfers that deliver XRP based on PREIMAGE-SHA-256 crypto-conditions, and it executes those transfers within seconds of being presented with the matching fulfillment. + + \ No newline at end of file diff --git a/content/concepts/transactions/payments/partial-payments.md b/content/concepts/transactions/payments/partial-payments.md new file mode 100644 index 0000000000..6ac66aaa12 --- /dev/null +++ b/content/concepts/transactions/payments/partial-payments.md @@ -0,0 +1,138 @@ +--- +html: partial-payments.html +parent: payments.html +blurb: Partial payments are useful for returning payments without incurring additional costs to oneself. +labels: + - Transactions +--- +# Partial Payments + +In the default case, the `Amount` field of a `Payment` transaction in the XRP Ledger specifies the exact amount to deliver, after charging for exchange rates and [transfer fees. The "Partial Payment" flag (`tfPartialPayment`) allows a payment to succeed by reducing the amount received instead of increasing the amount sent. Partial payments are useful for returning payments without incurring additional costs to oneself. + + + + +The amount of XRP used for the [transaction cost](../transaction-cost.md) is always deducted from the sender’s account, regardless of the type of transaction. + +Partial payments can be used to exploit naive integrations with the XRP Ledger to steal money from exchanges and gateways. The [Partial Payments Exploit](#partial-payments-exploit) section of this document describes how this exploit works and how you can avoid it. + +## Semantics + +### Without Partial Payments + +When sending a Payment that does not use the Partial Payment flag, the `Amount` field of the transaction specifies the exact amount to deliver, and the `SendMax` field specifies the maximum amount and currency to send. If a payment cannot deliver the full `Amount` without exceeding the `SendMax` parameter, or the full amount cannot be delivered for any other reason, the transaction fails. If the `SendMax` field is omitted from the transaction instructions, it is considered to be equal to the `Amount`. In this case, the payment can only succeed if the total amount of fees is 0. + +In other words: + + Amount + (fees) = (sent amount) ≤ SendMax + +In this formula, "fees" refers to [transfer fees](../../tokens/transfer-fees.md) and currency exchange rates. The "sent amount" and the delivered amount (`Amount`) may be denominated in different currencies and converted by consuming Offers in the XRP Ledger's decentralized exchange. + +**Note:** The `Fee` field of the transaction refers to the XRP [transaction cost](../transaction-cost.md), which is destroyed to relay the transaction to the network. The exact transaction cost specified is always debited from the sender and is completely separate from the fee calculations for any type of payment. + +### With Partial Payments + +When sending a Payment that has the Partial Payment flag enabled, the `Amount` field of the transaction specifies a maximum amount to deliver. Partial payments can succeed at sending _some_ of the intended value despite limitations including fees, not enough liquidity, not enough space in the receiving account's trust lines, or other reasons. + +The optional `DeliverMin` field specifies a minimum amount to deliver. The `SendMax` field functions the same as with non-partial payments. The partial payment transaction is successful if it delivers any amount equal or greater than the `DeliverMin` field without exceeding the `SendMax` amount. If the `DeliverMin` field is not specified, a partial payment can succeed by delivering any positive amount. + +In other words: + + Amount ≥ (Delivered Amount) = SendMax - (Fees) ≥ DeliverMin > 0 + +### Partial Payment Limitations + +Partial Payments have the following limitations: + +- A partial payment cannot provide the XRP to fund an address; this case returns the result code `telNO_DST_PARTIAL`. +- Direct XRP-to-XRP payments cannot be partial payments; this case returns the result code `temBAD_SEND_XRP_PARTIAL`. + - However, cross-currency payments that involve XRP as one of the currencies _can_ be partial payments. + + + +### The `delivered_amount` Field + +To help understand how much a partial payment actually delivered, the metadata of a successful Payment transaction includes a `delivered_amount` field. This field describes the amount actually delivered, in the same format as the `Amount` field. + + + +For non-partial payments, the `delivered_amount` field of the transaction metadata is equal to the `Amount` field of the transaction. When a payment delivers [tokens](../../tokens/tokens.md), the `delivered_amount` might be slightly different than the `Amount` field due to rounding. + +The delivered amount is **not available** for transactions that meet **both** of the following criteria: + +- Is a partial payment +- Is included in a validated ledger before 2014-01-20 + +If both conditions are true, then `delivered_amount` contains the string value `unavailable` instead of an actual amount. If this happens, you can only determine the actual delivered amount by reading the `AffectedNodes` in the transaction's metadata. If the transaction delivered tokens and the `issuer` of the `Amount` is the same account as the `Destination` address, the delivered amount may be divided among multiple `AffectedNodes` members representing trust lines to different counterparties. + +You can find the `delivered_amount` field in the following places: + +| API | Method | Field | +|-----|--------|-------| +| JSON-RPC / WebSocket | `account_tx` method | `result.transactions` array members' `meta.delivered_amount` | +| JSON-RPC / WebSocket | `tx` method | `result.meta.delivered_amount` | +| JSON-RPC / WebSocket | `transaction_entry` method | `result.metadata.delivered_amount` | +| JSON-RPC / WebSocket | `ledger` method (with transactions expanded) | `result.ledger.transactions` array members' `metaData.delivered_amount` New in: rippled 1.2.1 | +| WebSocket | Transaction subscriptions](subscribe.md#transaction-streams) | Subscription messages' `meta.delivered_amount` New in: rippled 1.2.1 | +| ripple-lib v1.x | `getTransaction` method | `outcome.deliveredAmount` | +| ripple-lib v1.x | `getTransactions` method | array members' `outcome.deliveredAmount` | + +WebSocket: http-websocket-apis.html +JSON-RPC / WebSocket: http-websocket-apis.html + + + + +## Partial Payments Exploit + +If a financial institution's integration with the XRP Ledger assumes that the `Amount` field of a Payment is always the full amount delivered, malicious actors may be able to exploit that assumption to steal money from the institution. This exploit can be used against gateways, exchanges, or merchants as long as those institutions' software does not process partial payments correctly. + +**The correct way to process incoming Payment transactions is to use [the `delivered_amount` metadata field](#the-delivered_amount-field),** not the `Amount` field. This way, an institution is never mistaken about how much it _actually_ received. + + +### Exploit Scenario Steps + +To exploit a vulnerable financial institution, a malicious actor does something like this: + +1. The malicious actor sends a Payment transaction to the institution. This transaction has a large `Amount` field and has the **`tfPartialPayment`** flag enabled. +2. The partial payment succeeds (result code `tesSUCCESS`) but actually delivers a very small amount of the currency specified. +3. The vulnerable institution reads the transaction's `Amount` field without looking at the `Flags` field or `delivered_amount` metadata field. +4. The vulnerable institution credits the malicious actor in an external system, such as the institution's own ledger, for the full `Amount`, despite only receiving a much smaller `delivered_amount` in the XRP Ledger. +5. The malicious actor withdraws as much of the balance as possible to another system before the vulnerable institution notices the discrepancy. + - Malicious actors usually prefer to convert the balance to another crypto-currency such as Bitcoin, because blockchain transactions are usually irreversible. With a withdrawal to a fiat currency system, the financial institution may be able to reverse or cancel the transaction several days after it initially executes. + - In the case of an exchange, the malicious actor can also withdraw an XRP balance directly back into the XRP Ledger. + +In the case of a merchant, the order of operations is slightly different, but the concept is the same: + +1. The malicious actor requests to buy a large amount of goods or services. +2. The vulnerable merchant invoices the malicious actor for the price of those goods and services. +3. The malicious actor sends a Payment transaction to the merchant. This transaction has a large `Amount` field and has the **`tfPartialPayment`** flag enabled. +4. The partial payment succeeds (result code `tesSUCCESS`) but delivers only a very small amount of the currency specified. +5. The vulnerable merchant reads the transaction's `Amount` field without looking at the `Flags` field or `delivered_amount` metadata field. +6. The vulnerable merchant treats the invoice as paid and provides the goods or services to the malicious actor, despite only receiving a much smaller `delivered_amount` in the XRP Ledger. +7. The malicious actor uses, resells, or absconds with the goods and services before the merchant notices the discrepancy. + +### Further Mitigations + +Using [the `delivered_amount` field](#the-delivered_amount-field) when processing incoming transactions is enough to avoid this exploit. Still, additional proactive business practices can also avoid or mitigate the likelihood of this and similar exploits. For example: + +- Add additional sanity checks to your business logic for processing withdrawals. Never process a withdrawal if the total balance you hold in the XRP Ledger does not match your expected assets and obligations. +- Follow "Know Your Customer" guidelines and strictly verify your customers' identities. You may be able to recognize and block malicious users in advance, or pursue legal action against a malicious actor who exploits your system. + + \ No newline at end of file diff --git a/content/concepts/transactions/payments/payment-channels.md b/content/concepts/transactions/payments/payment-channels.md new file mode 100644 index 0000000000..32ce24304b --- /dev/null +++ b/content/concepts/transactions/payments/payment-channels.md @@ -0,0 +1,50 @@ +--- +html: payment-channels.html +parent: payments.html +blurb: Payment channels allow asynchronous XRP payments to be divided into smaller increments and settled later. +labels: + - Transactions +--- +# Payment Channels + +Payment Channels are an advanced feature for sending asynchronous XRP payments that can be divided into very small increments and settled later. + +The XRP for a payment channel is set aside temporarily. The sender creates _Claims_ against the channel, which the recipient verifies without sending an XRP Ledger transaction or waiting for a new ledger version to be approved by [consensus](consensus.html). (This is an _asynchronous_ process because it happens separate from the usual pattern of getting transactions approved by consensus.) At any time, the recipient can _redeem_ a Claim to receive an amount of XRP authorized by that Claim. Settling a Claim like this uses a standard XRP Ledger transaction, as part of the usual consensus process. This single transaction can encompass any number of transactions guaranteed by smaller Claims. + +Because Claims can be verified individually but settled in bulk later, payment channels make it possible to conduct transactions at a rate only limited by the participants' ability to create and verify the digital signatures of those Claims. This limit is primarily based on the speed of the participants' hardware and the complexity of the signature algorithms. For maximum speed, use Ed25519 signatures, which are faster than the XRP Ledger's default secp256k1 ECDSA signatures. Research has [demonstrated the ability to create over Ed25519 100,000 signatures per second and to verify over 70,000 per second](https://ed25519.cr.yp.to/ed25519-20110926.pdf) on commodity hardware in 2011. + + +## Why Use Payment Channels? + +The process of using a payment channel always involves two parties, a payer and a payee. The payer is an individual person or institution using the XRP Ledger who is a customer of the payee. The payee is a person or business who receives XRP as payment for goods or services. + +Payment Channels do not intrinsically specify anything about what you can buy and sell with them. However, the types of goods and services that are a good fit for payment channels are: + +- Things that can be transmitted near-instantly, like digital items +- Inexpensive things, where the cost of processing a transaction is a non-trivial part of the price +- Things normally bought in bulk, where the exact quantity desired is not known in advance + + +## Payment Channel Lifecycle + +The following diagram summarizes the lifecycle of a payment channel: + +{{ include_svg("img/paychan-flow.svg", "Payment Channel Flow Diagram") }} + + \ No newline at end of file diff --git a/content/concepts/transactions/payments/payments.md b/content/concepts/transactions/payments/payments.md new file mode 100644 index 0000000000..9cfd921897 --- /dev/null +++ b/content/concepts/transactions/payments/payments.md @@ -0,0 +1,33 @@ +--- +html: payments.html +parent: transactions.html +blurb: tef code definitions. +labels: + - Transactions +--- +# Payment Types + The XRP Ledger supports point-to-point XRP payments alongside other, more specialized payment types. + +- [Direct XRP Payments](direct-xrp-payments.md) + + Direct XRP payments are the simplest way to send value in the XRP Ledger. + +- [Cross-Currency Payments](cross-currency-payments.md) + + Cross-currency payments atomically deliver a different currency than they send by converting through paths and order books. + +- [Checks](checks.md) + + Checks let users create deferred payments that can be canceled or cashed by the intended recipients. + +- [Escrow](escrow.md) + + Escrows set aside XRP and deliver it later when certain conditions are met. Escrows can depend on time limits, cryptographic conditions, or both. + +- [Partial Payments](partial-payments.md) + + Partial payments subtract fees from the amount sent, delivering a flexible amount. Partial payments are useful for returning unwanted payments without incurring additional costs. + +- [Payment Channels](payment-channels.md) + + Payment Channels enable fast, asynchronous XRP payments that can be divided into very small increments and settled later. \ No newline at end of file diff --git a/content/concepts/transactions/source-and-destination-tags.md b/content/concepts/transactions/source-and-destination-tags.md new file mode 100644 index 0000000000..d38a045498 --- /dev/null +++ b/content/concepts/transactions/source-and-destination-tags.md @@ -0,0 +1,47 @@ +# Source and Destination Tags + +_Source tags_ and _destination tags_ are a feature of XRP Ledger [payments](../payments/payment-types.md) that can indicate specific purposes for payments from and to multi-purpose addresses. Source and destination tags do not have direct on-ledger functionality; source and destination tags merely provide information about how off-ledger systems should process a payment. In transactions, both source and destination tags are formatted as 32-bit unsigned integers. + +Destination tags indicate the beneficiary or destination for a payment. For example, a payment to an exchange or gateway address can use a destination tag to indicate which customer to credit for the amount of the payment in that business's own systems. A payment to a merchant could indicate what item or cart the payment is buying. + + + +Source tags indicate the originator or source of a payment. Most commonly, a Source Tag is included so that the recipient of the payment knows where to send a return, or "bounced", payment. When returning an incoming payment, you should use the source tag from the incoming payment as the destination tag of the outgoing (return) payment. + +The practice of giving customers the ability to send and receive transactions from your XRP Ledger address using another interface is called providing _hosted accounts_. Hosted accounts typically use source and destination tags for each customer. + +**Tip:** An [X-address](https://xrpaddress.info/) combines a classic address with a tag into a single address that encodes both. If you are showing a deposit address to customers, it may be easier for your customers to use an X-address rather than making them keep track of two pieces of information. (The tag in an X-address acts as a source tag when sending and a destination tag when receiving.) + +## Rationale + +In other distributed ledgers, it is common to use different deposit addresses for each customer. In the XRP Ledger, an address must be a funded, permanent [account](../accounts/accounts.md) to receive payments. Using this approach in the XRP Ledger wastefully consumes resources of all servers in the network, and is costly because the [reserve](../accounts/reserves.md) amount must be set aside indefinitely for each address. + +Source and destination tags provide a more lightweight way to map deposits and payments to individual customers. + +## Use Cases + +A business may want to use source and destination tags for several purposes: + +- Direct mappings to customer accounts. +- Matching return payments to the outgoing payments that prompted them. +- Mapping payments to quotes that expire. +- Providing disposable tags that customers can generate for specific deposits. + +To prevent overlap while protecting privacy, a business can divide the total range of tags available into sections for each purpose, then assign tags in an unpredictable order within the range. For example, use a cryptographic hash function like [SHA-256](https://en.wikipedia.org/wiki/SHA-2), then use the [modulo operator](https://en.wikipedia.org/wiki/Modulo_operation) to map the output to the size of the relevant section. To be safe, check for collisions with old tags before using a new tag. + +Assigning tags in numerical order provides less privacy to customers. Since all XRP Ledger transactions are public, assigning tags in this way can make it possible to guess which tags correspond to various users' addresses or to derive information about users' accounts based on the tags used. + + +## Requiring Tags + +For an XRP Ledger address that may receive payments intended for several customer accounts, receiving a payment _without_ a destination tag can be a problem: it is not immediately obvious which customer to credit, which can require a manual intervention and a discussion with the sender to figure out who was the intended recipient. To reduce cases like this, you can enable the `RequireDest` setting. That way, if a user forgets to include a destination tag in a payment, the XRP Ledger rejects their payment instead of giving you money you don't know what to do with. The user can then send the payment again, using the tag as they should have. + + \ No newline at end of file diff --git a/content/concepts/transactions/tickets.md b/content/concepts/transactions/tickets.md new file mode 100644 index 0000000000..6254420308 --- /dev/null +++ b/content/concepts/transactions/tickets.md @@ -0,0 +1,72 @@ +--- +html: tickets.html +parent: transactions.html +blurb: Tickets allow you to schedule transactions out of sequential order. +labels: + - Transactions +--- +# Tickets + +_(Added by the TicketBatch amendment.)_ + +A Ticket in the XRP Ledger is a way of setting aside a 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.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, 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. + +{{ include_svg("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. + +{{ include_svg("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](../accounts/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](../xrpl/consensus.md). However, transactions that fail to do what they were intended to do can still be confirmed by consensus with [`tec`-class result codes](./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](../accounts/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.html#calculate-and-share-validations).) +- To "cancel" a Ticket, use the Ticket to [perform a no-op](about-canceling-a-transaction.md) `AccountSet transaction`. This deletes the Ticket so that you don't have to meet its reserve requirement. + + + \ No newline at end of file diff --git a/content/concepts/transactions/transaction-cost.md b/content/concepts/transactions/transaction-cost.md new file mode 100644 index 0000000000..973aed5a8b --- /dev/null +++ b/content/concepts/transactions/transaction-cost.md @@ -0,0 +1,182 @@ +--- +html: transaction-cost.html +parent: transactions.html +blurb: Every transaction costs a small amount of XRP for purely practical reasons. +labels: + - Transactions +--- +# Transaction Cost + +To protect the XRP Ledger from being disrupted by spam and denial-of-service attacks, each transaction must destroy a small amount of [XRP](../../../introduction/what-is-xrp.md). This _transaction cost_ is designed to increase along with the load on the network, making it very expensive to deliberately or inadvertently overload the network. + +Every transaction must [specify how much XRP to destroy](#specifying-the-transaction-cost) to pay the transaction cost. + + +## Current Transaction Cost + +The current minimum transaction cost required by the network for a standard transaction is **0.00001 XRP** (10 drops). It sometimes increases due to higher than usual load. + +You can also [query `rippled` for the current transaction cost](#querying-the-transaction-cost). + +### Special Transaction Costs + +Some transactions have different transaction costs: + +| Transaction | Cost Before Load Scaling | +|-----------------------|--------------------------| +| [Reference Transaction](#reference-transaction-cost) (Most transactions) | 10 drops | +| [Key Reset Transaction](#key-reset-transaction) | 0 | +| [Multi-signed Transaction](multi-signing.md) | 10 drops × (1 + Number of Signatures Provided) | +| EscrowFinish Transaction with Fulfillment | 10 drops × (33 + (Fulfillment size in bytes ÷ 16)) | +| [AccountDelete Transaction](accounts.html#deletion-of-accounts) | 2,000,000 drops | + + + +## Beneficiaries of the Transaction Cost + +The transaction cost is not paid to any party: the XRP is irrevocably destroyed. + +## Load Cost and Open Ledger Cost + +When the `FeeEscalation` amendment is enabled, there are two thresholds for the transaction cost: + +* If the transaction cost does not meet a `rippled` server's [load-based transaction cost threshold](#local-load-cost), the server ignores the transaction completely. (This logic is essentially unchanged with or without the amendment.) +* If the transaction cost does not meet a `rippled` server's [open ledger cost threshold](#open-ledger-cost), the server queues the transaction for a later ledger. + +This divides transactions into roughly three categories: + +* Transactions that specify a transaction cost so low that they get rejected by the load-based transaction cost. +* Transactions that specify a transaction cost high enough to be included in the current open ledger. +* Transactions in between, which get [queued for a later ledger version](#queued-transactions). + + +## Local Load Cost + +Each `rippled` server maintains a cost threshold based on its current load. If you submit a transaction with a `Fee` value that is lower than current load-based transaction cost of the `rippled` server, that server neither applies nor relays the transaction. (**Note:** If you submit a transaction through an admin connection, the server applies and relays the transaction as long as the transaction meets the un-scaled minimum transaction cost.) A transaction is very unlikely to survive [the consensus process](../xrpl/consensus.md) unless its `Fee` value meets the requirements of a majority of servers. + + + + +## Open Ledger Cost + +The `rippled` server has a second mechanism for enforcing the transaction cost, called the _open ledger cost_. A transaction can only be included in the open ledger if it meets the open ledger cost requirement in XRP. Transactions that do not meet the open ledger cost may be [queued for a following ledger](#queued-transactions) instead. + +For each new ledger version, the server picks a soft limit on the number of transactions to be included in the open ledger, based on the number of transactions in the previous ledger. The open ledger cost is equal to the minimum un-scaled transaction cost until the number of transactions in the open ledger is equal to the soft limit. After that, the open ledger cost increases exponentially for each transaction included in the open ledger. For the next ledger, the server increases the soft limit if the current ledger contained more transactions than the soft limit, and decreases the soft limit if the consensus process takes more than 5 seconds. + +The open ledger cost requirement is [proportional to the normal cost of the transaction](#fee-levels), not the absolute transaction cost. Transaction types that have a higher-than-normal requirement, such as [multi-signed transactions](multi-signing.md) must pay more to meet the open ledger cost than transactions which have minimum transaction cost requirements. + +See also: [Fee Escalation explanation in `rippled` repository](https://github.com/ripple/rippled/blob/release/src/ripple/app/misc/FeeEscalation.md). + +### Queued Transactions + +When `rippled` receives a transaction that meets the server's local load cost but not the [open ledger cost](#open-ledger-cost), the server estimates whether the transaction is "likely to be included" in a later ledger. If so, the server adds the transaction to the transaction queue and relays the transaction to other members of the network. Otherwise, the server discards the transaction. The server tries to minimize the amount of network load caused by transactions that would not pay a transaction cost, since [the transaction cost only applies when a transaction is included in a validated ledger](#transaction-costs-and-failed-transactions). + +For more information on queued transactions, see [Transaction Queue](../server/transaction-queue.md). + +## Reference Transaction Cost + +The "Reference Transaction" is the cheapest (non-free) transaction, in terms of the necessary [transaction cost](transaction-cost.md) before load scaling. Most transactions have the same cost as the reference transaction. Some transactions, such as [multi-signed transactions](multi-signing.md), require a multiple of this cost instead. When the open ledger cost escalates, the requirement is proportional to the basic cost of the transaction. + +### Fee Levels + +_Fee levels_ represent the proportional difference between the minimum cost and the actual cost of a transaction. The [Open Ledger Cost](#open-ledger-cost) is measured in fee levels instead of absolute cost. See the following table for a comparison: + +| Transaction | Minimum cost in drops | Minimum cost in Fee levels | Double cost in drops | Double cost in fee levels | +|-------------|-----------------------|----------------------------|----------------------|---------------------------| +| Reference transaction (most transactions) | 10 | 256 | 20 | 512 | +| [Multi-signed transaction](multi-signing.md) with 4 signatures | 50 | 256 | 100 | 512 | +| [Key reset transaction](transaction-cost.md#key-reset-transaction) | 0 | (Effectively infinite) | N/A | (Effectively infinite) | +| EscrowFinish transaction with 32-byte preimage. | 350 | 256 | 700 | 512 | + + + +## Querying the Transaction Cost + +The `rippled` APIs have two ways to query the local load-based transaction cost: the `server_info` command (intended for humans) and the `server_state` command (intended for machines). + +If the `FeeEscalation` amendment is enabled, you can use the `fee` method to check the open ledger cost. + +### server_info + +The `server_info` method reports the unscaled minimum XRP cost, as of the previous ledger, as `validated_ledger.base_fee_xrp`, in the form of decimal XRP. The actual cost necessary to relay a transaction is scaled by multiplying that `base_fee_xrp` value by the `load_factor` parameter in the same response, which represents the server's current load level. In other words: + +**Current Transaction Cost in XRP = `base_fee_xrp` × `load_factor`** + + +### server_state + +The `server_state` method returns a direct representation of `rippled`'s internal load calculations. In this case, the effective load rate is the ratio of the current `load_factor` to the `load_base`. The `validated_ledger.base_fee` parameter reports the minimum transaction cost in drops of XRP. This design enables `rippled` to calculate the transaction cost using only integer math, while still allowing a reasonable amount of fine-tuning for server load. The actual calculation of the transaction cost is as follows: + +**Current Transaction Cost in Drops = (`base_fee` × `load_factor`) ÷ `load_base`** + + + +## Specifying the Transaction Cost + +Every signed transaction must include the transaction cost in the [`Fee` field](transaction-common-fields.md). Like all fields of a signed transaction, this field cannot be changed without invalidating the signature. + +As a rule, the XRP Ledger executes transactions _exactly_ as they are signed. (To do anything else would be difficult to coordinate across a decentralized consensus network, at the least.) As a consequence of this, every transaction destroys the exact amount of XRP specified by the `Fee` field, even if the specified amount is much more than the current minimum transaction cost for any part of the network. The transaction cost can even destroy XRP that would otherwise be set aside for an account's [reserve requirement](reserves.html). + +Before signing a transaction, we recommend [looking up the current load-based transaction cost](#querying-the-transaction-cost). If the transaction cost is high due to load scaling, you may want to wait for it to decrease. If you do not plan on submitting the transaction immediately, we recommend specifying a slightly higher transaction cost to account for future load-based fluctuations in the transaction cost. + + +### Automatically Specifying the Transaction Cost + +The `Fee` field is one of the things that can be [auto-filled](transaction-common-fields.md#auto-fillable-fields) when creating a transaction. In this case, the auto-filling software provides a suitable `Fee` value based on the current load in the peer-to-peer network. However, there are several drawbacks and limitations to automatically filling in the transaction cost in this manner: + +- If the network's transaction cost goes up between auto-filling and submitting the transaction, the transaction may not be confirmed. + - To prevent a transaction from getting stuck in a state of being neither definitively confirmed or rejected, be sure to provide a `LastLedgerSequence` parameter so it eventually expires. Alternatively, you can try to [cancel a stuck transaction](about-canceling-a-transaction.md) by reusing the same `Sequence` number. + + + +- You have to be careful that the automatically provided value isn't too high. You don't want to burn a large fee to send a small transaction. + - If you are using `rippled`, you can also use the `fee_mult_max` and `fee_div_max` parameters of the `sign` method to set a limit to the load scaling you are willing to sign. + - Some client libraries (like [xrpl.js](https://js.xrpl.org/) and [xrpl-py](https://xrpl-py.readthedocs.io/)) have configurable maximum `Fee` values, and raise an error instead of signing a transaction whose `Fee` value is higher than the maximum. +- You cannot auto-fill from an offline machine nor when [multi-signing](multi-signing.html). + + +## Transaction Costs and Failed Transactions + +Since the purpose of the transaction cost is to protect the XRP Ledger peer-to-peer network from excessive load, it should apply to any transaction that gets distributed to the network, regardless of whether or not that transaction succeeds. However, to affect the shared global ledger, a transaction must be included in a validated ledger. Thus, `rippled` servers try to include failed transactions in ledgers, with [`tec` status codes](./transaction-results/transaction-results.md) ("tec" stands for "Transaction Engine - Claimed fee only"). + +The transaction cost is only debited from the sender's XRP balance when the transaction actually becomes included in a validated ledger. This is true whether the transaction is considered successful or fails with a `tec` code. + +If a transaction's failure is [final](finality-of-results.md), the `rippled` server does not relay it to the network. The transaction does not get included in a validated ledger, so it cannot have any effect on anyone's XRP balance. + +### Insufficient XRP + +When a `rippled` server initially evaluates a transaction, it rejects the transaction with the error code `terINSUF_FEE_B` if the sending account does not have a high enough XRP balance to pay the XRP transaction cost. Since this is a `ter` (Retry) code, the `rippled` server retries the transaction without relaying it to the network, until the transaction's outcome is [final](finality-of-results.md). + +When a transaction has already been distributed to the network, but the account does not have enough XRP to pay the transaction cost, the result code `tecINSUFF_FEE` occurs instead. In this case, the account pays all the XRP it can, ending with 0 XRP. This can occur because `rippled` decides whether to relay the transaction to the network based on its in-progress ledger, but transactions may be dropped or reordered when building the consensus ledger. + + +## Key Reset Transaction + +As a special case, an account can send a `SetRegularKey` transaction with a transaction cost of `0`, as long as the account's `lsfPasswordSpent` flag is disabled. This transaction must be signed by the account's _master key pair_. Sending this transaction enables the `lsfPasswordSpent` flag. + +This feature is designed to allow you to recover an account if the regular key is compromised, without worrying about whether the compromised account has any XRP available. This way, you can regain control of the account before you send more XRP to it. + +The `lsfPasswordSpent` flag starts out disabled. It gets enabled when you send a SetRegularKey transaction signed by the master key pair. It gets disabled again when the account receives a payment of XRP. + +When the `FeeEscalation` amendment is enabled, `rippled` prioritizes key reset transactions above other transactions even though the nominal transaction cost of a key reset transaction is zero. + + +## Changing the Transaction Cost + +The XRP Ledger has a mechanism for changing the minimum transaction cost to account for long-term changes in the value of XRP. Any changes have to be approved by the consensus process. See [Fee Voting](../xrpl/fee-voting.md) for more information. + + \ No newline at end of file diff --git a/content/concepts/transactions/transaction-history.md b/content/concepts/transactions/transaction-history.md new file mode 100644 index 0000000000..d7ed81eb4f --- /dev/null +++ b/content/concepts/transactions/transaction-history.md @@ -0,0 +1,24 @@ +--- +html: transaction-history.html +parent: transactions.html +blurb: You can trace the history of transactions for a particular account. +labels: + - Transactions +--- +# Transaction History + +In the XRP Ledger, transaction history is tracked by a "thread" of transactions linked by a transaction's identifying hash and the ledger index. The `AccountRoot` ledger object has the identifying hash and ledger of the transaction that most recently modified it; the metadata of that transaction includes the previous state of the `AccountRoot` node, so it is possible to iterate through the history of a single account this way. This transaction history includes any transactions that modify the `AccountRoot` node directly, including: + +- Transactions sent by the account, because they modify the account's `Sequence` number. These transactions also modify the account's XRP balance because of the transaction cost. +- Transactions that modified the account's XRP balance, including incoming `Payment` transactions and other types of transactions such as `PaymentChannelClaim` and `EscrowFinish`. + +The _conceptual_ transaction history of an account also includes transactions that modified the account's owned objects and non-XRP balances. These objects are separate ledger objects, each with their own thread of transactions that affected them. If you have an account's full ledger history, you can follow it forward to find the ledger objects created or modified by it. A "complete" transaction history includes the history of objects owned by a transaction, such as: + +- `RippleState` objects (Trust Lines) connected to the account. +- `DirectoryNode` objects, especially the owner directory tracking the account's owned objects. +- `Offer` objects, representing the account's outstanding currency-exchange orders in the decentralized exchange +- `PayChannel` objects, representing asynchronous payment channels to and from the account +- `Escrow` objects, representing held payments to or from the account that are locked by time or a crypto-condition. +- `SignerList` objects, representing lists of addresses that can authorize transactions for the account by multi-signing. + +For more information on each of these objects, see the Ledger Format Reference. diff --git a/content/concepts/transactions/transaction-malleability.md b/content/concepts/transactions/transaction-malleability.md new file mode 100644 index 0000000000..0dbadc64d2 --- /dev/null +++ b/content/concepts/transactions/transaction-malleability.md @@ -0,0 +1,148 @@ +--- +html: transaction-malleability.html +parent: transactions.html +blurb: Every transaction costs a small amount of XRP for purely practical reasons. +labels: + - Transactions +--- +# Transaction Malleability + +A transaction is "malleable" if it can be changed in any way after being signed, without the keys to sign it. In the XRP Ledger, the _functionality_ of a signed transaction cannot change, but in some circumstances a third party _could_ change the signature and identifying hash of a transaction. + +If vulnerable software submits malleable transactions and assumes they can only execute under the original hash, it may lose track of transactions. In the worst case, malicious actors could take advantage of this to steal money from the vulnerable system. + +On the XRP Ledger mainnet, only _multi-signed_ transactions can be malleable, if they have more signatures than necessary, or if an authorized signer provides an additional signature beyond what is necessary. Good operational security can protect against these problems. See [Mitigations for Multi-Signature Malleability](#mitigations-for-multi-signature-malleability) for guidelines. + +Before 2014, single-signed transactions could be malleable due to properties of the default signing algorithm, ECDSA with the secp256k1 curve. For compatibility with legacy signing tools, it was possible to create and submit malleable single-signed transactions until the RequireFullyCanonicalSig amendment became enabled on 2020-07-03. (Transactions [signed with Ed25519 keys](../accounts/cryptographic-keys.md#signing-algorithms) were never vulnerable to this problem.) + + + +## Background + +In the XRP Ledger, a transaction cannot execute unless: + +- All [fields of a transaction](transaction-common-fields.md) are signed, except the signature itself. +- The key pair(s) used to sign the transaction are [authorized to send transactions on behalf of that account](transaction-basics.md#authorizing-transactions). +- The signature is _canonical_ and matches the transaction instructions. + +Any change to the signed fields, no matter how small, would invalidate the signature, so no part of the transaction can be malleable except for the signature itself. In most cases, any change to a signature itself also invalidates the signature, but there are some specific exceptions, described below. + +Since the signature is among the data used to compute a transaction's identifying hash, any changes to a malleable transaction result in a different hash. + +### Alternate secp256k1 Signatures + +To be "canonical", signatures created with the ECDSA algorithm and secp256k1 curve (the default) must meet the following requirements: + +- The signature must be properly [DER-encoded data](https://en.wikipedia.org/wiki/X.690#DER_encoding). +- The signature must not have any padding bytes outside the DER-encoded data. +- The signature's component integers must not be negative, and they must not be larger than the secp256k1 group order. + +Generally speaking, any standard ECDSA implementation handles these requirements automatically. However, with secp256k1, those requirements are insufficient to prevent malleability. Thus, the XRP Ledger has a concept of "fully canonical" signatures which do not have the same problem. + +An ECDSA signature consists of two integers, called R and S. The secp256k1 _group order_, called N, is a constant value for all secp256k1 signatures. Specifically, N is the value `0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141`. For any given signature `(R,S)`, the signature `(R, N-S)` (that is, using N minus S in place of S) is also valid. + +Thus, to have _fully_ canonical signatures, one must choose which of the two possibilities is preferred and declare the other to be invalid. The creators of the XRP Ledger decided arbitrarily to prefer the _smaller_ of the two possible values, `S` or `N-S`. A transaction is considered _fully canonical_ if it uses the preferred (smaller) value of `S`, and follows all the normal rules for being canonical. To calculate a fully-canonical ECDSA signature, one must compare S and N-S to determine which is smaller, then use that value in the `Signature` field of the transaction. + +With the RequireFullyCanonicalSig amendment (enabled in 2020), all transactions must use _fully canonical_ signatures only. + +Between 2014 and 2020, the XRP Ledger was compatible with legacy software that did not always generate fully canonical signatures, but used a flag on transactions called [**`tfFullyCanonicalSig`**](transaction-common-fields.md#global-flags) to protect compatible software from transaction malleability. This flag, which compatible signing software enables by default, required that the transaction use a _fully-canonical_ signature to be valid. Now that the RequireFullyCanonicalSig amendment is enabled, the flag is no longer necessary, but there is no harm in enabling it anyway. + + +### Malleability with Multi-Signatures + +An important, explicit feature of multi-signing is that multiple different possible configurations can make a transaction valid. For example, an account can be configured so that signatures from any three of five signers could authorize a transaction. However, this inherently means that there can be several different variations of a valid transaction, each with a different identifying hash. + +All of the following cases can lead to transaction malleability: + +- If a transaction still has enough signatures to meet its quorum after removing one or more. Any third party could remove a signature and re-submit the transaction without it. +- If one can add a valid signature to a transaction that already has a quorum. Only an authorized signer of the sending account could create such a signature. +- If one can replace one signature from a transaction with another valid signature while maintaining a quorum. Only an authorized signer of the sending account could create such a signature. + +Even if your authorized signers are not intentionally malicious, confusion or poor coordination could cause several signers to submit different valid versions of the same transaction. + +#### Mitigations for Multi-Signature Malleability + +**Good operational security can protect against these problems.** Generally, you can avoid transaction malleability problems when multi-signing if you follow good operational security practices, including the following: + +- Do not collect more signatures than necessary. +- Either appoint one party to assemble a transaction after collecting the necessary number of signatures, or instruct signers pass the transaction instructions forward to be signed in a set order. +- Do not add unnecessary or untrusted signers to your multi-signing lists, even if the `weight` values associated with their keys are insufficient to authorize a transaction. +- Be prepared for the possibility that a transaction executes with a different hash and set of signatures than you expected. Carefully monitor your account's sent transactions (for example, using the `account_tx` method). +- Monitor the `Sequence` number of your account (for example, using the `account_info method`). This number always increases by exactly one when your account sends a transaction successfully, and never any other way. If the number does not match what you expect, you should check your recent transactions to confirm why. (Aside from malleable transactions, there are other ways this could happen, too. Perhaps you configured another application to send transactions for you. Maybe a malicious user gained access to your secret key. Or perhaps your application lost data and forgot about a transaction you sent already.) +- If you re-create transactions to be multi-signed, _do not_ change the `Sequence` number unless you have manually confirmed that the intended actions have not already executed. +- Confirm that the `tfFullyCanonicalSig` flag is enabled before signing. + +For greater security, these guidelines provide multiple layers of protection. + + +## Exploit With Malleable Transactions + +If the software you use to interface with the XRP Ledger sends malleable transactions, a malicious actor might be able to trick your software into losing track of a transaction's final outcome and potentially (in the worst case) sending equivalent payments multiple times. + +If you use single-signatures only, you are not vulnerable to this exploit. If you use multi-signatures, you might be vulnerable if you or your signers provide more signatures than necessary. + +### Exploit Scenario Steps + +The process to exploit a vulnerable system follows a series of steps like the following: + +1. The vulnerable system constructs a multi-signed transaction and collects more than the necessary number of signatures. + + If an authorized signer is malicious or irresponsible, the transaction could also be vulnerable if that signer's signature is not included but could be added. + +2. The system notes the identifying hash of the vulnerable transaction, submits it to the XRP Ledger network, then begins monitoring for that hash to be included in a validated ledger version. + +3. A malicious actor sees the transaction propagating through the network before it becomes confirmed. + +4. The malicious actor removes an extra signature from the vulnerable transaction. + + Unlike creating a signature for different transaction instructions, this does not require a large amount of computational work. It can be done in much less time than it takes to generate a signature in the first place. + + Alternatively, an authorized signer whose signature is not already part of the transaction could add their signature to the vulnerable transaction's list of signatures. Depending on the sender's multi-signing settings, this can be instead of or in addition to removing other signatures from the transaction. + + The modified list of signatures results in a different identifying hash. (You do not have to calculate the hash before you submit to the network, but knowing the hash makes it easier to check the transaction's status later.) + +5. The malicious actor submits the modified transaction to the network. + + This creates a "race" between the transaction as originally submitted and the modified version submitted by the malicious actor. The two transactions are mutually exclusive. Both are valid, but they have the same exact transaction data, including the `Sequence` number, so at most one of them can ever be included in a validated ledger. + + Servers in the peer-to-peer network have no way of knowing which one "came first" or was intended by its original sender. Delays or other coincidences in network connectivity could result in validators seeing only one or the other by the time they finalize their consensus proposals, so either one could "win the race". + + A malicious actor could increase the chances of getting non-canonical transactions confirmed if they controlled some number of well-connected servers in the peer-to-peer network, even if those servers are not trusted as validators. + + If the malicious actor controls the only server to which the vulnerable system submitted the transaction, the malicious actor can easily control which version is distributed to the rest of the network. + +6. The malicious actor's version of the transaction achieves consensus and becomes included in a validated ledger. + + At this point, the transaction has executed and cannot be reversed. Its effects (such as sending XRP) are final. The original version of the transaction is no longer valid because its `Sequence` number has been used. + + The effects of the transaction in the XRP Ledger are exactly the same as if the original version had executed. + +7. The vulnerable system does not see the transaction hash it is expecting, and erroneously concludes that the transaction did not execute. + + If the transaction included the `LastLedgerSequence` field, this would occur after the specified ledger index has passed. + + If the transaction omitted the `LastLedgerSequence` field, this could be wrong in another way: if no other transaction from the same sender uses the same `Sequence` number, then the transaction could theoretically succeed later regardless of how much time has passed. + + + +8. The vulnerable system takes action assuming that the transaction has failed. + + For example, it may refund (or not debit) a customer's balance in its own system, to account for the funds that it thinks have not been sent in the XRP Ledger. + + Worse, the vulnerable system might construct a new transaction to replace the transaction, picking new `Sequence`, `LastLedgerSequence`, and `Fee` parameters based on the current state of the network, but keeping the rest of the transaction the same as the original. If this new transaction is also malleable, the system could be exploited in the same way an indefinite number of times. + + \ No newline at end of file diff --git a/content/concepts/transactions/transaction-metadata-concept.md b/content/concepts/transactions/transaction-metadata-concept.md new file mode 100644 index 0000000000..36d3aaa888 --- /dev/null +++ b/content/concepts/transactions/transaction-metadata-concept.md @@ -0,0 +1,1574 @@ +--- +html: transaction-metadata-concept.html +parent: transactions.html +blurb: Transaction metadata is a section of data that is added to a transaction after it is processed. +labels: + - Ledgers +--- +# Transaction Metadata + +Transaction metadata is a section of data that gets added to a transaction after it is processed. Any transaction that gets included in a ledger has metadata, regardless of whether it is successful. The transaction metadata describes the outcome of the transaction in detail. + +The changes described in transaction metadata are only final if the transaction is in a validated ledger version. + +Some fields that might appear in transaction metadata include: + +| Field | Value | Description | +|:----------------------------------------|:--------------------|:-------------| +| `AffectedNodes` | Array | List of ledger objects that were created, deleted, or modified by this transaction, and specific changes to each. | +| `DeliveredAmount` | Currency Amount | _(May be omitted)_ For a [partial payment](payments/partial-payments.md), this field records the amount of currency actually delivered to the destination. To avoid errors when reading transactions, instead use the `delivered_amount` field, which is provided for all Payment transactions, partial or not. | +| `TransactionIndex` | Unsigned Integer | The transaction's position within the ledger that included it. This is zero-indexed. (For example, the value `2` means it was the 3rd transaction in that ledger.) | +| `TransactionResult` | String | A [result code](transaction-results.html) indicating whether the transaction succeeded or how it failed. | +| [`delivered_amount`](transaction-metadata.html#delivered_amount) | Currency Amount | _(Omitted for non-Payment transactions)_ The Currency Amount actually received by the `Destination` account. Use this field to determine how much was delivered, regardless of whether the transaction is a [partial payment](payments/partial-payments.md). See [this description](transaction-metadata.md#delivered_amount) for details. | + +## Example Metadata + +The following JSON object shows the metadata for [a complex cross-currency payment](https://xrpcharts.ripple.com/#/transactions/8C55AFC2A2AA42B5CE624AEECDB3ACFDD1E5379D4E5BF74A8460C5E97EF8706B): + +```json +{ + "AffectedNodes": [ + { + "ModifiedNode": { + "FinalFields": { + "Account": "r9ZoLsJHzMMJLpvsViWQ4Jgx17N8cz1997", + "Balance": "77349986", + "Flags": 0, + "OwnerCount": 2, + "Sequence": 9 + }, + "LedgerEntryType": "AccountRoot", + "LedgerIndex": "1E7E658C2D3DF91EFAE5A12573284AD6F526B8F64DD12F013C6F889EF45BEA97", + "PreviousFields": { + "OwnerCount": 3 + }, + "PreviousTxnID": "55C11248ACEFC2EFD59755BF88867783AC18EA078517108F942069C2FBE4CF5C", + "PreviousTxnLgrSeq": 35707468 + } + }, + { + "ModifiedNode": { + "FinalFields": { + "Balance": { + "currency": "USD", + "issuer": "rrrrrrrrrrrrrrrrrrrrBZbvji", + "value": "2298.927882138068" + }, + "Flags": 1114112, + "HighLimit": { + "currency": "USD", + "issuer": "rLEsXccBGNR3UPuPu2hUXPjziKC3qKSBun", + "value": "0" + }, + "HighNode": "000000000000006B", + "LowLimit": { + "currency": "USD", + "issuer": "rpvvAvaZ7TXHkNLM8UJwCTU6yBU2jDTJ1P", + "value": "1000000000" + }, + "LowNode": "0000000000000007" + }, + "LedgerEntryType": "RippleState", + "LedgerIndex": "220DDA7164F3F41F3C5223FA3125D4CD368EBB4FB954B5FBFFB6D1EA6DACDD5E", + "PreviousFields": { + "Balance": { + "currency": "USD", + "issuer": "rrrrrrrrrrrrrrrrrrrrBZbvji", + "value": "2297.927882138068" + } + }, + "PreviousTxnID": "1DB2F9C67C3F42F7B8AB02BA2264254A78A201EC8A9974A1CACEFD51545B1263", + "PreviousTxnLgrSeq": 43081739 + } + }, + { + "ModifiedNode": { + "FinalFields": { + "Balance": { + "currency": "USD", + "issuer": "rrrrrrrrrrrrrrrrrrrrBZbvji", + "value": "33403.80553244443" + }, + "Flags": 1114112, + "HighLimit": { + "currency": "USD", + "issuer": "rhub8VRN55s94qWKDv6jmDy1pUykJzF3wq", + "value": "0" + }, + "HighNode": "0000000000001A40", + "LowLimit": { + "currency": "USD", + "issuer": "rd5Sx93pCMgfxwBuofjen2csoFYmY8VrT", + "value": "1000000000" + }, + "LowNode": "0000000000000000" + }, + "LedgerEntryType": "RippleState", + "LedgerIndex": "38569918AF54B520463CFDDD00EB5ADD8768039BD94E61A5E25C387EA4FDC9A3", + "PreviousFields": { + "Balance": { + "currency": "USD", + "issuer": "rrrrrrrrrrrrrrrrrrrrBZbvji", + "value": "33402.80752845242" + } + }, + "PreviousTxnID": "38A0E82ADC2DA6C6D59929B73E9812CD1E1384E452FD23D0717EA0037E2FC9E3", + "PreviousTxnLgrSeq": 43251694 + } + }, + { + "ModifiedNode": { + "FinalFields": { + "Account": "rBndiPPKs9k5rjBb7HsEiqXKrz8AfUnqWq", + "BookDirectory": "4627DFFCFF8B5A265EDBD8AE8C14A52325DBFEDAF4F5C32E5B09B13AC59DBA5E", + "BookNode": "0000000000000000", + "Flags": 0, + "OwnerNode": "0000000000000000", + "Sequence": 407556, + "TakerGets": { + "currency": "USD", + "issuer": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B", + "value": "75.1379833998197" + }, + "TakerPays": "204986996" + }, + "LedgerEntryType": "Offer", + "LedgerIndex": "557BDD35E40EAFFE0AC98108A0F4AC4BB812A168CFD5B4E35475F42A60ABD9C8", + "PreviousFields": { + "TakerGets": { + "currency": "USD", + "issuer": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B", + "value": "76.1399833998197" + }, + "TakerPays": "207720593" + }, + "PreviousTxnID": "961C575073788979815F103D065CEE449D2EA6EFE8FC8C33C26EC08586925D90", + "PreviousTxnLgrSeq": 43251680 + } + }, + { + "ModifiedNode": { + "FinalFields": { + "Account": "r9KG7Du7aFmABzMvDnwuvPaEoMu4Eurwok", + "Balance": "8080207629", + "Flags": 0, + "OwnerCount": 6, + "Sequence": 1578765 + }, + "LedgerEntryType": "AccountRoot", + "LedgerIndex": "5A667CB5FBAB4143EDEFBD6EDDD4B6D19C905209C8EE16486D5D7CD6CB083E78", + "PreviousFields": { + "Balance": "8080152531", + "Sequence": 1578764 + }, + "PreviousTxnID": "E3CDFD288620871455634DC1E56439136AACA1DDBCE987BE12F97486AB477375", + "PreviousTxnLgrSeq": 43251694 + } + }, + { + "DeletedNode": { + "FinalFields": { + "Account": "r9ZoLsJHzMMJLpvsViWQ4Jgx17N8cz1997", + "BookDirectory": "A6D5D1C1CC92D56FDDFD4434FB10BD31F63EB991DA3C756653071AFD498D0000", + "BookNode": "0000000000000000", + "Flags": 0, + "OwnerNode": "0000000000000000", + "PreviousTxnID": "DB028A461E98B0398CAD65F2871B381A6D0B9A21662CA5B033438D83C518C0F2", + "PreviousTxnLgrSeq": 35686129, + "Sequence": 7, + "TakerGets": { + "currency": "EUR", + "issuer": "rhub8VRN55s94qWKDv6jmDy1pUykJzF3wq", + "value": "2.5" + }, + "TakerPays": { + "currency": "ETH", + "issuer": "rcA8X3TVMST1n3CJeAdGk1RdRCHii7N2h", + "value": "0.05" + } + }, + "LedgerEntryType": "Offer", + "LedgerIndex": "6AA7E5121FEB456F0A899E3D6F25D62ABB408BB67B91C9270E13714401ED72B5" + } + }, + { + "ModifiedNode": { + "FinalFields": { + "Account": "rd5Sx93pCMgfxwBuofjen2csoFYmY8VrT", + "Balance": "8251028196", + "Flags": 0, + "OwnerCount": 4, + "Sequence": 274 + }, + "LedgerEntryType": "AccountRoot", + "LedgerIndex": "6F830A1B38F827CD4BEC946A40F1E2DF726FC22AFC3918FD621567AF17F49F3A", + "PreviousFields": { + "Balance": "8253816902" + }, + "PreviousTxnID": "38A0E82ADC2DA6C6D59929B73E9812CD1E1384E452FD23D0717EA0037E2FC9E3", + "PreviousTxnLgrSeq": 43251694 + } + }, + { + "ModifiedNode": { + "FinalFields": { + "Account": "rd5Sx93pCMgfxwBuofjen2csoFYmY8VrT", + "BookDirectory": "79C54A4EBD69AB2EADCE313042F36092BE432423CC6A4F784E0CB6D74F25A336", + "BookNode": "0000000000000000", + "Flags": 0, + "OwnerNode": "0000000000000000", + "Sequence": 273, + "TakerGets": "8246341599", + "TakerPays": { + "currency": "USD", + "issuer": "rhub8VRN55s94qWKDv6jmDy1pUykJzF3wq", + "value": "2951.147613535471" + } + }, + "LedgerEntryType": "Offer", + "LedgerIndex": "7FD1EAAE17B7D68AE640FFC56CECC3999B4F938EFFF6EA6887B6CC8BD9DBDC63", + "PreviousFields": { + "TakerGets": "8249130305", + "TakerPays": { + "currency": "USD", + "issuer": "rhub8VRN55s94qWKDv6jmDy1pUykJzF3wq", + "value": "2952.145617527486" + } + }, + "PreviousTxnID": "38A0E82ADC2DA6C6D59929B73E9812CD1E1384E452FD23D0717EA0037E2FC9E3", + "PreviousTxnLgrSeq": 43251694 + } + }, + { + "ModifiedNode": { + "FinalFields": { + "Balance": { + "currency": "USD", + "issuer": "rrrrrrrrrrrrrrrrrrrrBZbvji", + "value": "-11.68225001668339" + }, + "Flags": 131072, + "HighLimit": { + "currency": "USD", + "issuer": "r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59", + "value": "5000" + }, + "HighNode": "0000000000000000", + "LowLimit": { + "currency": "USD", + "issuer": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B", + "value": "0" + }, + "LowNode": "000000000000004A" + }, + "LedgerEntryType": "RippleState", + "LedgerIndex": "826CF5BFD28F3934B518D0BDF3231259CBD3FD0946E3C3CA0C97D2C75D2D1A09", + "PreviousFields": { + "Balance": { + "currency": "USD", + "issuer": "rrrrrrrrrrrrrrrrrrrrBZbvji", + "value": "-10.68225001668339" + } + }, + "PreviousTxnID": "28B271F7C27C1A267F32FFCD8B1795C5D3B1DC761AD705E3A480139AA8B61B09", + "PreviousTxnLgrSeq": 43237130 + } + }, + { + "ModifiedNode": { + "FinalFields": { + "Account": "rBndiPPKs9k5rjBb7HsEiqXKrz8AfUnqWq", + "Balance": "8276201534", + "Flags": 0, + "OwnerCount": 5, + "Sequence": 407558 + }, + "LedgerEntryType": "AccountRoot", + "LedgerIndex": "880C6FB7B9C0083211F950E4449AD45895C0EC1114B5112CE1320AC7275E3237", + "PreviousFields": { + "Balance": "8273467937" + }, + "PreviousTxnID": "CB4B54942F11510A47D2731C3260429093F24016B366CBF15D8EC4B705372F02", + "PreviousTxnLgrSeq": 43251683 + } + }, + { + "ModifiedNode": { + "FinalFields": { + "Balance": { + "currency": "USD", + "issuer": "rrrrrrrrrrrrrrrrrrrrBZbvji", + "value": "-6557.745685633666" + }, + "Flags": 2228224, + "HighLimit": { + "currency": "USD", + "issuer": "rBndiPPKs9k5rjBb7HsEiqXKrz8AfUnqWq", + "value": "1000000000" + }, + "HighNode": "0000000000000000", + "LowLimit": { + "currency": "USD", + "issuer": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B", + "value": "0" + }, + "LowNode": "0000000000000512" + }, + "LedgerEntryType": "RippleState", + "LedgerIndex": "8A9FEE5192E334195314B5C162BC78F7452ADB14E06839D48943BAE05EE1967F", + "PreviousFields": { + "Balance": { + "currency": "USD", + "issuer": "rrrrrrrrrrrrrrrrrrrrBZbvji", + "value": "-6558.747685633666" + } + }, + "PreviousTxnID": "961C575073788979815F103D065CEE449D2EA6EFE8FC8C33C26EC08586925D90", + "PreviousTxnLgrSeq": 43251680 + } + }, + { + "ModifiedNode": { + "FinalFields": { + "Balance": { + "currency": "GCB", + "issuer": "rrrrrrrrrrrrrrrrrrrrBZbvji", + "value": "9990651675.348776" + }, + "Flags": 3211264, + "HighLimit": { + "currency": "GCB", + "issuer": "rHaans8PtgwbacHvXAL3u6TG28gTAtCwr8", + "value": "0" + }, + "HighNode": "0000000000000000", + "LowLimit": { + "currency": "GCB", + "issuer": "r9KG7Du7aFmABzMvDnwuvPaEoMu4Eurwok", + "value": "10000000000" + }, + "LowNode": "0000000000000000" + }, + "LedgerEntryType": "RippleState", + "LedgerIndex": "A2B41EE7818A5756B6A2276BDBB3CE0ED3A3B350787FD6B76E5EA1354A8F20D2", + "PreviousFields": { + "Balance": { + "currency": "GCB", + "issuer": "rrrrrrrrrrrrrrrrrrrrBZbvji", + "value": "9990651678.137482" + } + }, + "PreviousTxnID": "961C575073788979815F103D065CEE449D2EA6EFE8FC8C33C26EC08586925D90", + "PreviousTxnLgrSeq": 43251680 + } + }, + { + "DeletedNode": { + "FinalFields": { + "ExchangeRate": "53071AFD498D0000", + "Flags": 0, + "RootIndex": "A6D5D1C1CC92D56FDDFD4434FB10BD31F63EB991DA3C756653071AFD498D0000", + "TakerGetsCurrency": "0000000000000000000000004555520000000000", + "TakerGetsIssuer": "2ADB0B3959D60A6E6991F729E1918B7163925230", + "TakerPaysCurrency": "0000000000000000000000004554480000000000", + "TakerPaysIssuer": "06CC4A6D023E68AA3499C6DE3E9F2DC52B8BA254" + }, + "LedgerEntryType": "DirectoryNode", + "LedgerIndex": "A6D5D1C1CC92D56FDDFD4434FB10BD31F63EB991DA3C756653071AFD498D0000" + } + }, + { + "ModifiedNode": { + "FinalFields": { + "Flags": 0, + "Owner": "r9ZoLsJHzMMJLpvsViWQ4Jgx17N8cz1997", + "RootIndex": "A83C1B192A27582EDB320EBD7A3FE58D7042CE04B67A2B3D87FDD63D871E12D7" + }, + "LedgerEntryType": "DirectoryNode", + "LedgerIndex": "A83C1B192A27582EDB320EBD7A3FE58D7042CE04B67A2B3D87FDD63D871E12D7" + } + }, + { + "ModifiedNode": { + "FinalFields": { + "Balance": { + "currency": "USD", + "issuer": "rrrrrrrrrrrrrrrrrrrrBZbvji", + "value": "0" + }, + "Flags": 65536, + "HighLimit": { + "currency": "USD", + "issuer": "rLEsXccBGNR3UPuPu2hUXPjziKC3qKSBun", + "value": "0" + }, + "HighNode": "0000000000000002", + "LowLimit": { + "currency": "USD", + "issuer": "r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59", + "value": "1" + }, + "LowNode": "0000000000000000" + }, + "LedgerEntryType": "RippleState", + "LedgerIndex": "C493ABA2619D0FC6355BA862BC8312DF8266FBE76AFBA9636E857F7EAC874A99", + "PreviousFields": { + "Balance": { + "currency": "USD", + "issuer": "rrrrrrrrrrrrrrrrrrrrBZbvji", + "value": "1" + } + }, + "PreviousTxnID": "28B271F7C27C1A267F32FFCD8B1795C5D3B1DC761AD705E3A480139AA8B61B09", + "PreviousTxnLgrSeq": 43237130 + } + }, + { + "ModifiedNode": { + "FinalFields": { + "Account": "r9KG7Du7aFmABzMvDnwuvPaEoMu4Eurwok", + "BookDirectory": "E6E8A9842EA2ED1FD5D0599343692CE1EBF977AEA751B7DC5B038D7EA4C68000", + "BookNode": "0000000000000000", + "Flags": 65536, + "OwnerNode": "0000000000000000", + "Sequence": 39018, + "TakerGets": { + "currency": "GCB", + "issuer": "rHaans8PtgwbacHvXAL3u6TG28gTAtCwr8", + "value": "9990651675.348776" + }, + "TakerPays": "9990651675348776" + }, + "LedgerEntryType": "Offer", + "LedgerIndex": "C939B9B2C5803DD6D89B792E72470F79CBE9F9E999691789E0B68C3808BDDD8E", + "PreviousFields": { + "TakerGets": { + "currency": "GCB", + "issuer": "rHaans8PtgwbacHvXAL3u6TG28gTAtCwr8", + "value": "9990651678.137482" + }, + "TakerPays": "9990651678137482" + }, + "PreviousTxnID": "961C575073788979815F103D065CEE449D2EA6EFE8FC8C33C26EC08586925D90", + "PreviousTxnLgrSeq": 43251680 + } + }, + { + "ModifiedNode": { + "FinalFields": { + "Balance": { + "currency": "USD", + "issuer": "rrrrrrrrrrrrrrrrrrrrBZbvji", + "value": "2963.413395452545" + }, + "Flags": 65536, + "HighLimit": { + "currency": "USD", + "issuer": "rhub8VRN55s94qWKDv6jmDy1pUykJzF3wq", + "value": "0" + }, + "HighNode": "0000000000001A97", + "LowLimit": { + "currency": "USD", + "issuer": "rpvvAvaZ7TXHkNLM8UJwCTU6yBU2jDTJ1P", + "value": "0" + }, + "LowNode": "0000000000000007" + }, + "LedgerEntryType": "RippleState", + "LedgerIndex": "E4D1FBD5CB72A1D3EE38C21F3BCB13E454FCB469CD01C1366E0008A031E6A7FC", + "PreviousFields": { + "Balance": { + "currency": "USD", + "issuer": "rrrrrrrrrrrrrrrrrrrrBZbvji", + "value": "2964.413395452545" + } + }, + "PreviousTxnID": "1DB2F9C67C3F42F7B8AB02BA2264254A78A201EC8A9974A1CACEFD51545B1263", + "PreviousTxnLgrSeq": 43081739 + } + } + ], + "DeliveredAmount": { + "currency": "GCB", + "issuer": "rHaans8PtgwbacHvXAL3u6TG28gTAtCwr8", + "value": "2.788706" + }, + "TransactionIndex": 38, + "TransactionResult": "tesSUCCESS", + "delivered_amount": { + "currency": "GCB", + "issuer": "rHaans8PtgwbacHvXAL3u6TG28gTAtCwr8", + "value": "2.788706" + } +} +``` + +## AffectedNodes + +The `AffectedNodes` array contains a complete list of the [objects in the ledger][] that this transaction modified in some way. Each entry in this array is an object with one top-level field indicating what type it is: + +- `CreatedNode` indicates that the transaction created a new object in the ledger. +- `DeletedNode` indicates that the transaction removed an object from the ledger. +- `ModifiedNode` indicates that the transaction modified an existing object in the ledger. + +The value of each of these fields is a JSON object describing the changes made to the ledger object. + +### CreatedNode Fields + +A `CreatedNode` object contains the following fields: + +| Field | Value | Description | +|:------------------|:------------------|:-------------------------------------| +| `LedgerEntryType` | String | The type of [ledger object](../../../references/protocol-reference/ledger-data/ledger-object-types/ledger-object-types.md) that was created. | +| `LedgerIndex` | String - Hash | The [ID of this ledger object](../../../references/protocol-reference/ledger-data/ledger-object-ids.md) in the ledger's [state tree](../xrpl/ledgers.md). **Note:** This is _not__ the same as a [ledger index](../../../references/protocol-reference/data-types/basic-data-types.md#ledger-index), even though the field name is very similar. | +| `NewFields` | Object | The content fields of the newly-created ledger object. Which fields are present depends on what type of ledger object was created. | + +### DeletedNode Fields + +A `DeletedNode` object contains the following fields: + +| Field | Value | Description | +|:------------------|:------------------|:-------------------------------------| +| `LedgerEntryType` | String | The [type of ledger object][] that was deleted. | +| `LedgerIndex` | String - [Hash][] | The [ID of this ledger object](../../../references/protocol-reference/ledger-data/ledger-object-ids.md) in the ledger's [state tree](ledgers.html). **Note:** This is **not the same** as a [ledger index](../../../references/protocol-reference/data-types/basic-data-types.md#ledger-index), even though the field name is very similar. | +| `FinalFields` | Object | The content fields of the ledger object immediately before it was deleted. Which fields are present depends on what type of ledger object was created. | + +### ModifiedNode Fields + +A `ModifiedNode` object contains the following fields: + +| Field | Value | Description | +|:--------------------|:--------------------------|:---------------------------| +| `LedgerEntryType` | String | The [type of ledger object](../../../references/protocol-reference/ledger-data/ledger-object-types/ledger-object-types.md) that was deleted. | +| `LedgerIndex` | String - Hash | The [ID of this ledger object](../../../references/protocol-reference/ledger-data/ledger-object-ids.md) in the ledger's [state tree](../xrpl/ledgers.md). **Note:** This is **not the same** as a [ledger index](../../../references/protocol-reference/data-types/basic-data-types.md#ledger-index), even though the field name is very similar. | +| `FinalFields` | Object | The content fields of the ledger object after applying any changes from this transaction. Which fields are present depends on what type of ledger object was created. This omits the `PreviousTxnID` and `PreviousTxnLgrSeq` fields, even though most types of ledger objects have them. | +| `PreviousFields` | Object | The previous values for all fields of the object that were changed as a result of this transaction. If the transaction _only added_ fields to the object, this field is an empty object. | +| `PreviousTxnID` | String - Hash | _(May be omitted)_ The identifying hash of the previous transaction to modify this ledger object. Omitted for ledger object types that do not have a `PreviousTxnID` field. | +| `PreviousTxnLgrSeq` | Number - Ledger Index | _(May be omitted)_ The Ledger Index of the ledger version containing the previous transaction to modify this ledger object. Omitted for ledger object types that do not have a `PreviousTxnLgrSeq` field. | + +**Note:** If the modified ledger object has `PreviousTxnID` and `PreviousTxnLgrSeq` fields, the transaction always updates them with the transaction's own identifying hash and the index of the ledger version that included the transaction, but these fields' new value is not listed in the `FinalFields` of the `ModifiedNode` object, and their previous values are listed at the top level of the `ModifiedNode` object rather than in the nested `PreviousFields` object. + + +## delivered_amount + +The `Amount` of a `Payment` transaction indicates the amount to deliver to the `Destination`, so if the transaction was successful, then the destination received that much -- _except if the transaction was a [partial payment](payments/partial-payments.md)_. (In that case, any positive amount up to `Amount` might have arrived.) Rather than choosing whether or not to trust the `Amount` field, you should use the `delivered_amount` field of the metadata to see how much actually reached its destination. + +The `rippled` server provides a `delivered_amount` field in JSON transaction metadata for all successful Payment transactions. This field is formatted like a normal currency amount. However, the delivered amount is not available for transactions that meet both of the following criteria: + +* Is a partial payment +* Included in a validated ledger before 2014-01-20 + +If both conditions are true, then `delivered_amount` contains the string value `unavailable` instead of an actual amount. If this happens, you can only figure out the actual delivered amount by reading the `AffectedNodes` in the transaction's metadata. + +**Note:** The `delivered_amount` field is generated on-demand for the request, and is not included in the binary format for transaction metadata, nor is it used when calculating the hash of the transaction metadata. In contrast, the `DeliveredAmount` field _is_ included in the binary format for partial payment transactions after 2014-01-20. + +See also: [Partial Payments](payments/partial-payments.md) + + + + + + \ No newline at end of file diff --git a/content/concepts/transactions/transaction-results/tec-codes-concepts.md b/content/concepts/transactions/transaction-results/tec-codes-concepts.md new file mode 100644 index 0000000000..9c755a89b6 --- /dev/null +++ b/content/concepts/transactions/transaction-results/tec-codes-concepts.md @@ -0,0 +1,1064 @@ +--- +html: tec-codes-concepts.html +parent: transaction-results-concepts.html +blurb: tec code definitions. +labels: + - Transactions +--- +# tec Codes + +These codes indicate that the transaction failed, but it was applied to a ledger to apply the [transaction cost](../transaction-cost.md). They have numerical values in the range 100 to 199. Ripple recommends using the text code, not the numeric value. + +For the most part, transactions with `tec` codes take no action other than to destroy the XRP paid as a [transaction cost](../transaction-cost.md), but there are some exceptions. As one such exception, a transaction that results in `tecOVERSIZE` still cleans up some unfunded offers. Always look at the [transaction metadata](../transaction-metadata.md) to see precisely what a transaction did. + + + +**Caution:** A transaction that provisionally failed with a `tec` code may still succeed or fail with a different code after being reapplied. The result is final when it appears in a validated ledger version. For more information, see [Finality of Results](../finality-of-results.md) + + +| Code | Value | Explanation | +|:---------------------------|:------|:----------------------------------------| +| `tecCLAIM` | 100 | Unspecified failure, with transaction cost destroyed. | +| `tecCRYPTOCONDITION_ERROR` | 146 | This `EscrowCreate` or `EscrowFinish` transaction contained a malformed or mismatched crypto-condition. | +| `tecDIR_FULL` | 121 | The transaction tried to add an object (such as a trust line, Check, Escrow, or Payment Channel) to an account's owner directory, but that account cannot own any more objects in the ledger. | +| `tecDUPLICATE` | 149 | The transaction tried to create an object (such as a `DepositPreauth` authorization) that already exists. | +| `tecDST_TAG_NEEDED` | 143 | The `Payment` transaction omitted a [destination tag](../source-and-destination-tags.md), but the destination account has the `lsfRequireDestTag` flag enabled. [New in: rippled 0.28.0][] | +| `tecEXPIRED` | 148 | The transaction tried to create an object (such as an Offer or a Check) whose provided Expiration time has already passed. | +| `tecFAILED_PROCESSING` | 105 | An unspecified error occurred when processing the transaction. | +| `tecFROZEN` | 137 | The `OfferCreate` transaction failed because one or both of the assets involved are subject to a [global freeze](../../tokens/freezing-tokens.md). | +| `tecHAS_OBLIGATIONS` | 151 | The `AccountDelete` transaction failed because the account to be deleted owns objects that cannot be deleted. See [Deletion of Accounts](../../accounts/account-deleting.md) for details. | +| `tecINSUF_RESERVE_LINE` | 122 | The transaction failed because the sending account does not have enough XRP to create a new trust line. (See: [Reserves](../../accounts/reserves.md)) This error occurs when the counterparty already has a trust line in a non-default state to the sending account for the same currency. (See `tecNO_LINE_INSUF_RESERVE` for the other case.) | +| `tecINSUF_RESERVE_OFFER` | 123 | The transaction failed because the sending account does not have enough XRP to create a new Offer. (See: [Reserves](../../accounts/reserves.md)) | +| `tecINSUFF_FEE` | 136 | The transaction failed because the sending account does not have enough XRP to pay the [transaction cost](../transaction-cost.md) that it specified. (In this case, the transaction processing destroys all of the sender's XRP even though that amount is lower than the specified transaction cost.) This result only occurs if the account's balance decreases _after_ this transaction has been distributed to enough of the network to be included in a consensus set. Otherwise, the transaction fails with [`terINSUF_FEE_B`](ter-codes.md) before being distributed. | +| `tecINSUFFICIENT_RESERVE` | 141 | The transaction would increase the [reserve requirement](../../accounts/reserves.md) higher than the sending account's balance. `SignerListSet`, `PaymentChannelCreate`, `PaymentChannelFund`, and `EscrowCreate` can return this error code. See [Signer Lists and Reserves](../../../../references/protocol-reference/ledger-data/ledger-object-types/signerlist.md#signer-lists-and-reserves) for more information. | +| `tecINTERNAL` | 144 | Unspecified internal error, with transaction cost applied. This error code should not normally be returned. If you can reproduce this error, please [report an issue](https://github.com/ripple/rippled/issues). | +| `tecINVARIANT_FAILED` | 147 | An invariant check failed when trying to execute this transaction. Added by the EnforceInvariants amendment. If you can reproduce this error, please [report an issue](https://github.com/ripple/rippled/issues). | +| `tecKILLED` | 150 | The OfferCreate transaction specified the `tfFillOrKill` flag and could not be filled, so it was killed. _(Added by the fix1578 amendment.)_ | +| `tecNEED_MASTER_KEY` | 142 | This transaction tried to cause changes that require the master key, such as [disabling the master key or giving up the ability to freeze balances](../../../../references/protocol-reference/transactions/transaction-types/accountset.md#accountset-flags). [New in: rippled 0.28.0][] | +| `tecNO_ALTERNATIVE_KEY` | 130 | The transaction tried to remove the only available method of [authorizing transactions](../transactions.md#authorizing-transactions). This could be a `SetRegularKey` transaction to remove the regular key, a `SignerListSet transaction` to delete a SignerList, or an `AccountSet` transaction to disable the master key. (Prior to `rippled` 0.30.0, this was called `tecMASTER_DISABLED`.) | +| `tecNO_AUTH` | 134 | The transaction failed because it needs to add a balance on a trust line to an account with the `lsfRequireAuth` flag enabled, and that trust line has not been authorized. If the trust line does not exist at all, `tecNO_LINE` occurs instead. | +| `tecNO_DST` | 124 | The account on the receiving end of the transaction does not exist. This includes Payment and TrustSet transaction types. (It could be created if it received enough XRP.) | +| `tecNO_DST_INSUF_XRP` | 125 | The account on the receiving end of the transaction does not exist, and the transaction is not sending enough XRP to create it. | +| `tecNO_ENTRY` | 140 | The transaction tried to modify a [ledger object](../../../../references/protocol-reference/ledger-data/ledger-object-types/ledger-object-types.md), such as a [Check](../payments/checks.md), [Payment Channel](../payments/payment-channels.md), or [Deposit Preauthorization](../../../../references/protocol-reference/ledger-data/ledger-object-types/depositpreauth.md), but the specified object does not exist. It might have already been deleted by a previous transaction or the transaction might have an incorrect value in an ID field such as `CheckID`, `Channel`, `Unauthorize`. | +| `tecNO_ISSUER` | 133 | The account specified in the `issuer` field of a currency amount does not exist. | +| `tecNO_LINE` | 135 | The `TakerPays` field of the `OfferCreate` transaction specifies an asset whose issuer has `lsfRequireAuth` enabled, and the account making the offer does not have a trust line for that asset. (Normally, making an offer implicitly creates a trust line if necessary, but in this case it does not bother because you cannot hold the asset without authorization.) If the trust line exists, but is not authorized, `tecNO_AUTH` occurs instead. | +| `tecNO_LINE_INSUF_RESERVE` | 126 | The transaction failed because the sending account does not have enough XRP to create a new trust line. (See: [Reserves](../../accounts/reserves.md)) This error occurs when the counterparty does not have a trust line to this account for the same currency. (See `tecINSUF_RESERVE_LINE` for the other case.) | +| `tecNO_LINE_REDUNDANT` | 127 | The transaction failed because it tried to set a trust line to its default state, but the trust line did not exist. | +| `tecNO_PERMISSION` | 139 | The sender does not have permission to do this operation. For example, the `EscrowFinish` transaction tried to release a held payment before its `FinishAfter` time, someone tried to use `PaymentChannelFund` on a channel the sender does not own, or a `Payment` tried to deliver funds to an account with the "DepositAuth" flag enabled. | +| `tecNO_REGULAR_KEY` | 131 | The `AccountSet` transaction tried to disable the master key, but the account does not have another way to [authorize transactions](../transactions.md#authorizing-transactions). If [multi-signing](../multi-signing.md) is enabled, this code is deprecated and `tecNO_ALTERNATIVE_KEY` is used instead. | +| `tecNO_TARGET` | 138 | The transaction referenced an Escrow or PayChannel ledger object that doesn't exist, either because it never existed or it has already been deleted. (For example, another `EscrowFinish` transaction has already executed the held payment.) Alternatively, the destination account has `asfDisallowXRP` set so it cannot be the destination of this `PaymentChannelCreate` or `EscrowCreate` transaction. | +| `tecOVERSIZE` | 145 | This transaction could not be processed, because the server created an excessively large amount of [metadata](../transaction-metadata.md) when it tried to apply the transaction. [New in: rippled 0.29.0-hf1][] | +| `tecOWNERS` | 132 | The transaction requires that account sending it has a nonzero "owners count", so the transaction cannot succeed. For example, an account cannot enable the [`lsfRequireAuth`](../../../references/protocol-reference/transactions/transaction-types/accountset.md#accountset-flags) flag if it has any trust lines or available offers. | +| `tecPATH_DRY` | 128 | The transaction failed because the provided [paths](paths.html) did not have enough liquidity to send anything at all. This could mean that the source and destination accounts are not linked by [trust lines](../trust-lines-and-issuing.md). | +| `tecPATH_PARTIAL` | 101 | The transaction failed because the provided [paths](../../tokens/paths.md) did not have enough liquidity to send the full amount. | +| `tecTOO_SOON` | 152 | The `AccountDelete` transaction failed because the account to be deleted had a `Sequence` number that is too high. The current ledger index must be at least 256 higher than the account's sequence number. | +| `tecUNFUNDED` | 129 | The transaction failed because the account does not hold enough XRP to pay the amount in the transaction _and_ satisfy the additional [reserve](../../accounts/reserves.md) necessary to execute this transaction. | +| `tecUNFUNDED_ADD` | 102 | **DEPRECATED.** | +| `tecUNFUNDED_PAYMENT` | 104 | The transaction failed because the sending account is trying to send more XRP than it holds, not counting the [reserve](../../accounts/reserves.md). | +| `tecUNFUNDED_OFFER` | 103 | The `OfferCreate` transaction failed because the account creating the offer does not have any of the `TakerGets` currency. | + + + \ No newline at end of file diff --git a/content/concepts/transactions/transaction-results/tef-codes-concepts.md b/content/concepts/transactions/transaction-results/tef-codes-concepts.md new file mode 100644 index 0000000000..8d07ef4389 --- /dev/null +++ b/content/concepts/transactions/transaction-results/tef-codes-concepts.md @@ -0,0 +1,1044 @@ +--- +html: tef-codes-concepts.html +parent: transaction-success-concepts.html +blurb: tef code definitions. +labels: + - Transactions +--- +# tef Codes + + +These codes indicate that the transaction failed and was not included in a ledger, but the transaction could have succeeded in some theoretical ledger. Typically this means that the transaction can no longer succeed in any future ledger. They have numerical values in the range -199 to -100. The exact code for any given error is subject to change, so don't rely on it. + +**Caution:** Transactions with `tef` codes are not applied to ledgers and cannot cause any changes to the XRP Ledger state. However, a transaction that provisionally failed may still succeed or fail with a different code after being reapplied. For more information, see [Finality of Results](../finality-of-results.md) and Reliable Transaction Submission. + + +| Code | Explanation | +|:-----------------------|:----------------------------------------------------| +| `tefALREADY` | The same exact transaction has already been applied. | +| `tefBAD_ADD_AUTH` | **DEPRECATED.** | +| `tefBAD_AUTH` | The key used to sign this account is not authorized to modify this account. (It could be authorized if the account had the same key set as the [Regular Key](../../accounts/cryptographic-keys.md).) | +| `tefBAD_AUTH_MASTER` | The single signature provided to authorize this transaction does not match the master key, but no regular key is associated with this address. | +| `tefBAD_LEDGER` | While processing the transaction, the ledger was discovered in an unexpected state. If you can reproduce this error, please [report an issue](https://github.com/ripple/rippled/issues) to get it fixed. | +| `tefBAD_QUORUM` | The transaction was [multi-signed](../multi-signing.md), but the total weights of all included signatures did not meet the quorum. | +| `tefBAD_SIGNATURE` | The transaction was [multi-signed](../multi-signing.md), but contained a signature for an address not part of a SignerList associated with the sending account. | +| `tefCREATED` | **DEPRECATED.** | +| `tefEXCEPTION` | While processing the transaction, the server entered an unexpected state. This may be caused by unexpected inputs, for example if the binary data for the transaction is grossly malformed. If you can reproduce this error, please [report an issue](https://github.com/ripple/rippled/issues) to get it fixed. | +| `tefFAILURE` | Unspecified failure in applying the transaction. | +| `tefINTERNAL` | When trying to apply the transaction, the server entered an unexpected state. If you can reproduce this error, please [report an issue](https://github.com/ripple/rippled/issues) to get it fixed. | +| `tefINVARIANT_FAILED` | An invariant check failed when trying to claim the [transaction cost](../transaction-cost.md). Added by the EnforceInvariants amendment. If you can reproduce this error, please [report an issue](https://github.com/ripple/rippled/issues). | +| `tefMASTER_DISABLED` | The transaction was signed with the account's master key, but the account has the `lsfDisableMaster` field set. | +| `tefMAX_LEDGER` | The transaction included a `LastLedgerSequence`parameter, but the current ledger's sequence number is already higher than the specified value. | +| `tefNO_AUTH_REQUIRED` | The `TrustSet` transaction tried to mark a trust line as authorized, but the `lsfRequireAuth` flag is not enabled for the corresponding account, so authorization is not necessary. | +| `tefNO_TICKET` | The transaction attempted to use a [Ticket](../tickets.md), but the specified `TicketSequence` number does not exist in the ledger, and cannot be created in the future because it is earlier than the sender's current sequence number. | +| `tefNOT_MULTI_SIGNING` | The transaction was [multi-signed](../multi-signing.md), but the sending account has no SignerList defined. | +| `tefPAST_SEQ` | The sequence number of the transaction is lower than the current sequence number of the account sending the transaction. | +| `tefTOO_BIG` | The transaction would affect too many objects in the ledger. For example, this was an `AccountDelete` transaction but the account to be deleted owns over 1000 objects in the ledger. | +| `tefWRONG_PRIOR` | The transaction contained an `AccountTxnID` field (or the deprecated `PreviousTxnID` field), but the transaction specified there does not match the account's previous transaction. | + + + + + \ No newline at end of file diff --git a/content/concepts/transactions/transaction-results/tel-codes-concepts.md b/content/concepts/transactions/transaction-results/tel-codes-concepts.md new file mode 100644 index 0000000000..9963055b6f --- /dev/null +++ b/content/concepts/transactions/transaction-results/tel-codes-concepts.md @@ -0,0 +1,1035 @@ +--- +html: tel-codes-concepts.html +parent: transaction-results-concepts.html +blurb: tel code definitions. +labels: + - Transactions +--- +# tel Codes + +These codes indicate an error in the local server processing the transaction; it is possible that another server with a different configuration or load level could process the transaction successfully. They have numerical values in the range -399 to -300. The exact code for any given error is subject to change, so don't rely on it. + +**Caution:** Transactions with `tel` codes are not applied to ledgers and cannot cause any changes to the XRP Ledger state. However, these transactions may be automatically cached and retried later. Transactions that provisionally failed may still succeed or fail with a different code after being reapplied. For more information, see [Finality of Results](../finality-of-results.md). + + + +| Code | Explanation | +|:----------------------|:-----------------------------------------------------| +| `telBAD_DOMAIN` | The transaction specified a domain value (for example, the `Domain` field of an `AccountSet` transaction) that cannot be used, probably because it is too long to store in the ledger. | +| `telBAD_PATH_COUNT` | The transaction contains too many paths for the local server to process. | +| `telBAD_PUBLIC_KEY` | The transaction specified a public key value (for example, as the `MessageKey` field of an `AccountSet` transaction) that cannot be used, probably because it is not the right length. | +| `telCAN_NOT_QUEUE` | The transaction did not meet the [open ledger cost](transaction-cost.html), but this server did not queue this transaction because it did not meet the [queuing restrictions](../../server/transaction-queue.md#queuing-restrictions). For example, a transaction returns this code when the sender already has 10 other transactions in the queue. You can try again later or sign and submit a replacement transaction with a higher transaction cost in the `Fee` field. | +| `telCAN_NOT_QUEUE_BALANCE` | The transaction did not meet the [open ledger cost](../transaction-cost.md) and also was not added to the transaction queue because the sum of potential XRP costs of already-queued transactions is greater than the expected balance of the account. You can try again later, or try submitting to a different server. New in: rippled 0.70.2 | +| `telCAN_NOT_QUEUE_BLOCKS` | The transaction did not meet the [open ledger cost](../transaction-cost.md) and also was not added to the transaction queue. This transaction could not replace an existing transaction in the queue because it would block already-queued transactions from the same sender by changing authorization methods. (This includes all `SetRegularKey` and `SignerListSet` transactions, as well as `AccountSet` transactions that change the `RequireAuth`/`OptionalAuth`, `DisableMaster`, or `AccountTxnID` flags.) You can try again later, or try submitting to a different server. New in: rippled 0.70.2 | +| `telCAN_NOT_QUEUE_BLOCKED` | The transaction did not meet the [open ledger cost](../transaction-cost.md) and also was not added to the transaction queue because a transaction queued ahead of it from the same sender blocks it. (This includes all `SetRegularKey` and `SignerListSet` transactions, as well as `AccountSet` transactions that change the `RequireAuth`/`OptionalAuth`, `DisableMaster`, or `AccountTxnID` flags.) You can try again later, or try submitting to a different server. New in: rippled 0.70.2 | +| `telCAN_NOT_QUEUE_FEE` | The transaction did not meet the [open ledger cost](../transaction-cost.md) and also was not added to the transaction queue. This code occurs when a transaction with the same sender and sequence number already exists in the queue and the new one does not pay a large enough transaction cost to replace the existing transaction. To replace a transaction in the queue, the new transaction must have a `Fee` value that is at least 25% more, as measured in [fee levels](../transaction-cost.md#fee-levels). You can increase the `Fee` and try again, send this with a higher `Sequence` number so it doesn't replace an existing transaction, or try sending to another server. New in: rippled 0.70.2 | +| `telCAN_NOT_QUEUE_FULL` | The transaction did not meet the [open ledger cost](../transaction-cost.md) and the server did not queue this transaction because this server's transaction queue is full. You could increase the `Fee` and try again, try again later, or try submitting to a different server. The new transaction must have a higher transaction cost, as measured in [fee levels](../transaction-cost.md#fee-levels), than the transaction in the queue with the smallest transaction cost. New in: rippled 0.70.2 | +| `telFAILED_PROCESSING` | An unspecified error occurred when processing the transaction. | +| `telINSUF_FEE_P` | The `Fee` from the transaction is not high enough to meet the server's current [transaction cost](../transaction-cost.md) requirement, which is derived from its load level and network-level requirements. If the individual server is too busy to process your transaction right now, it may cache the transaction and automatically retry later. | +| `telLOCAL_ERROR` | Unspecified local error. | +| `telNO_DST`_`PARTIAL` | The transaction is an XRP payment that would fund a new account, but the [`tfPartialPayment` flag](../payments/partial-payments.md) was enabled. This is disallowed. | + + + \ No newline at end of file diff --git a/content/concepts/transactions/transaction-results/tem-codes-concepts.md b/content/concepts/transactions/transaction-results/tem-codes-concepts.md new file mode 100644 index 0000000000..122a63eb1a --- /dev/null +++ b/content/concepts/transactions/transaction-results/tem-codes-concepts.md @@ -0,0 +1,1055 @@ +--- +html: tem-codes-concepts.html +parent: transaction-results-concepts.html +blurb: tem code definitions. +labels: + - Transactions +--- +# tem Codes + +These codes indicate that the transaction was malformed, and cannot succeed according to the XRP Ledger protocol. They have numerical values in the range -299 to -200. The exact code for any given error is subject to change, so don't rely on it. + +**Tip:** Transactions with `tem` codes are not applied to ledgers, and cannot cause any changes to XRP Ledger state. A `tem` result is final unless the rules for a valid transaction change. (For example, using functionality from an [Amendment](../../../../amendments/amendments.md) before that amendment is enabled results in `temDISABLED`; such a transaction could succeed later if it becomes valid when the amendment is enabled.) + +| Code | Explanation | +|:-----------------------------|:----------------------------------------------| +| `temBAD_AMOUNT` | An amount specified by the transaction (for example the destination `Amount` or `SendMax` values of a `Payment`) was invalid, possibly because it was a negative number. | +| `temBAD_AUTH_MASTER` | The key used to sign this transaction does not match the master key for the account sending it, and the account does not have a [Regular Key](../../accounts/cryptographic-keys.md) set. | +| `temBAD_CURRENCY` | The transaction improperly specified a currency field. | +| `temBAD_EXPIRATION` | The transaction improperly specified an expiration value, for example as part of an `OfferCreate` transaction. Alternatively, the transaction did not specify a required expiration value, for example as part of an `EscrowCreate` transaction. | +| `temBAD_FEE` | The transaction improperly specified its `Fee` value, for example by listing a non-XRP currency or some negative amount of XRP. | +| `temBAD_ISSUER` | The transaction improperly specified the `issuer` field of some currency included in the request. | +| `temBAD_LIMIT` | The `TrustSet` transaction improperly specified the `LimitAmount` value of a trust line. | +| `temBAD_OFFER` | The `OfferCreate` transaction specifies an invalid offer, such as offering to trade XRP for itself, or offering a negative amount. | +| `temBAD_PATH` | The `Payment` transaction specifies one or more [Paths](../../tokens/paths.md) improperly, for example including an issuer for XRP, or specifying an account differently. | +| `temBAD_PATH_LOOP` | One of the [Paths](../../tokens/paths.md) in the `Payment` transaction was flagged as a loop, so it cannot be processed in a bounded amount of time. | +| `temBAD_SEND_XRP_LIMIT` | The `Payment` transaction used the [`tfLimitQuality` flag](../../../../references/protocol-reference/transactions/transaction-types/payment.md#limit-quality) in a direct XRP-to-XRP payment, even though XRP-to-XRP payments do not involve any conversions. | +| `temBAD_SEND_XRP_MAX` | The `Payment` transaction included a `SendMax` field in a direct XRP-to-XRP payment, even though sending XRP should never require `SendMax`. (XRP is only valid in `SendMax` if the destination `Amount` is not XRP.) | +| `temBAD_SEND_XRP_NO_DIRECT` | The `Payment` transaction used the [`tfNoDirectRipple` flag](../../../../references/protocol-reference/transactions/transaction-types/payment.md#payment-flags) for a direct XRP-to-XRP payment, even though XRP-to-XRP payments are always direct. | +| `temBAD_SEND_XRP_PARTIAL` | The `Payment` transaction used the [`tfPartialPayment` flag](../payments/partial-payments.html) for a direct XRP-to-XRP payment, even though XRP-to-XRP payments should always deliver the full amount. | +| `temBAD_SEND_XRP_PATHS` | The `Payment` transaction included `Paths` while sending XRP, even though XRP-to-XRP payments should always be direct. | +| `temBAD_SEQUENCE` | The transaction is references a sequence number that is higher than its own `Sequence` number, for example trying to cancel an offer that would have to be placed after the transaction that cancels it. | +| `temBAD_SIGNATURE` | The signature to authorize this transaction is either missing, or formed in a way that is not a properly-formed signature. (See [`tecNO_PERMISSION`](tec-codes.md) for the case where the signature is properly formed, but not authorized for this account.) | +| `temBAD_SRC_ACCOUNT` | The `Account` on whose behalf this transaction is being sent (the "source account") is not a properly-formed [account](../../accounts/accounts.md) address. | +| `temBAD_TRANSFER_RATE` | The [`TransferRate` field of an AccountSet transaction](../../../../references/protocol-reference/transactions/transaction-types/accountset.md#transferrate) is not properly formatted or out of the acceptable range. | +| `temCANNOT_PREAUTH_SELF` | The sender of the `DepositPreauth` transaction was also specified as the account to preauthorize. You cannot preauthorize yourself. | +| `temDST_IS_SRC` | The transaction improperly specified a destination address as the `Account` sending the transaction. This includes trust lines (where the destination address is the `issuer` field of `LimitAmount`) and payment channels (where the destination address is the `Destination` field). | +| `temDST_NEEDED` | The transaction improperly omitted a destination. This could be the `Destination` field of a `Payment` transaction, or the `issuer` sub-field of the `LimitAmount` field fo a `TrustSet` transaction. | +| `temINVALID` | The transaction is otherwise invalid. For example, the transaction ID may not be the right format, the signature may not be formed properly, or something else went wrong in understanding the transaction. | +| `temINVALID_COUNT` | The transaction includes a `TicketCount` field, but the number of Tickets specified is invalid. | +| `temINVALID_FLAG` | The transaction includes a [Flag](../transaction-common-fields.html#flags-field) that does not exist, or includes a contradictory combination of flags. | +| `temMALFORMED` | Unspecified problem with the format of the transaction. | +| `temREDUNDANT` | The transaction would do nothing; for example, it is sending a payment directly to the sending account, or creating an offer to buy and sell the same currency from the same issuer. | +| `temREDUNDANT_SEND_MAX` | Removed in: rippled 0.28.0 | +| `temRIPPLE_EMPTY` | The `Payment` transaction includes an empty `Paths` field, but paths are necessary to complete this payment. | +| `temBAD_WEIGHT` | The `SignerListSet` transaction includes a `SignerWeight` that is invalid, for example a zero or negative value. | +| `temBAD_SIGNER` | The `SignerListSet` transaction includes a signer who is invalid. For example, there may be duplicate entries, or the owner of the SignerList may also be a member. | +| `temBAD_QUORUM` | The `SignerListSet` transaction has an invalid `SignerQuorum` value. Either the value is not greater than zero, or it is more than the sum of all signers in the list. | +| `temUNCERTAIN` | Used internally only. This code should never be returned. | +| `temUNKNOWN` | Used internally only. This code should never be returned. | +| `temDISABLED` | The transaction requires logic that is disabled. Typically this means you are trying to use an [amendment](../../../../amendments/amendments.md) that is not enabled for the current ledger. | + + + \ No newline at end of file diff --git a/content/concepts/transactions/transaction-results/ter-codes-concepts.md b/content/concepts/transactions/transaction-results/ter-codes-concepts.md new file mode 100644 index 0000000000..436eb74de7 --- /dev/null +++ b/content/concepts/transactions/transaction-results/ter-codes-concepts.md @@ -0,0 +1,1032 @@ +--- +html: ter-codes-concepts.html +parent: transaction-results-concepts.html +blurb: ter code definitions. +labels: + - Transactions +--- +# ter Codes + +These codes indicate that the transaction failed, but it could apply successfully in the future, usually if some other hypothetical transaction applies first. They have numerical values in the range -99 to -1. The exact code for any given error is subject to change, so don't rely on it. + +**Caution:** Transactions with `ter` codes are not applied the current ledger and cannot cause any changes to the XRP Ledger state. However, a transaction that provisionally failed may still succeed or fail with a different code after being automatically reapplied. For more information, see [Finality of Results](../finality-of-results.md). + +| Code | Explanation | +|:-----------------|:----------------------------------------------------------| +| `terFUNDS_SPENT` | **DEPRECATED.** | +| `terINSUF_FEE_B` | The account sending the transaction does not have enough XRP to pay the `Fee` specified in the transaction. | +| `terLAST` | Used internally only. This code should never be returned. | +| `terNO_ACCOUNT` | The address sending the transaction is not funded in the ledger (yet). | +| `terNO_AUTH` | The transaction would involve adding currency issued by an account with `lsfRequireAuth` enabled to a trust line that is not authorized. For example, you placed an offer to buy a currency you aren't authorized to hold. | +| `terNO_LINE` | Used internally only. This code should never be returned. | +| `terNO_RIPPLE` | Used internally only. This code should never be returned. | +| `terOWNERS` | The transaction requires that account sending it has a nonzero "owners count", so the transaction cannot succeed. For example, an account cannot enable the [`lsfRequireAuth`](../../../../references/protocol-reference/transactions/transaction-types/accountset.md#accountset-flags) flag if it has any trust lines or available offers. | +| `terPRE_SEQ` | The `Sequence` number of the current transaction is higher than the current sequence number of the account sending the transaction. | +| `terPRE_TICKET` | The transaction attempted to use a [Ticket](../tickets.md), but the specified `TicketSequence` number does not exist in the ledger. However, the Ticket could still be created by another transaction. | +| `terRETRY` | Unspecified retriable error. | +| `terQUEUED` | The transaction met the load-scaled [transaction cost](transaction-cost.html) but did not meet the open ledger requirement, so the transaction has been queued for a future ledger. | + + + \ No newline at end of file diff --git a/content/concepts/transactions/transaction-results/tes-success-concepts.md b/content/concepts/transactions/transaction-results/tes-success-concepts.md new file mode 100644 index 0000000000..fff0d27d5f --- /dev/null +++ b/content/concepts/transactions/transaction-results/tes-success-concepts.md @@ -0,0 +1,20 @@ +--- +html: tes-success-concept.html +parent: transaction-results-concepts.html +blurb: tesSUCCESS is the only code that indicates a transaction succeeded. +labels: + - Transaction Sending +--- +# tes Success + +The code `tesSUCCESS` is the only code that indicates a transaction succeeded. This does not always mean it accomplished what you expected it to do. (For example, an `OfferCancel` can "succeed" even if there is no offer for it to cancel.) The `tesSUCCESS` result uses the numerical value 0. + +| Code | Explanation | +|:-----------|:----------------------------------------------------------------| +| `tesSUCCESS` | The transaction was applied and forwarded to other servers. If this appears in a validated ledger, then the transaction's success is final. | + + \ No newline at end of file diff --git a/content/concepts/transactions/transaction-results/transaction-results-concepts.md b/content/concepts/transactions/transaction-results/transaction-results-concepts.md new file mode 100644 index 0000000000..97b2d3cb0c --- /dev/null +++ b/content/concepts/transactions/transaction-results/transaction-results-concepts.md @@ -0,0 +1,1057 @@ +--- +html: transaction-results-concepts.html +parent: transactions.html +blurb: Transaction result code definitions. +labels: + - Transactions +--- +# Transaction Results + +[[Source]](https://github.com/ripple/rippled/blob/master/src/ripple/protocol/TER.h "Source") + +The `rippled` server summarizes transaction results with result codes, which appear in fields such as `engine_result` and `meta.TransactionResult`. These codes are grouped into several categories of with different prefixes: + +| Category | Prefix | Description | +|:----------------------|:--------------------------|:-------------------------| +| Claimed cost only | [`tec`](tec-codes.md) | The transaction did not achieve its intended purpose, but the [transaction cost](transaction-cost.md) was destroyed. This result is only final in a validated ledger. | +| Failure | [`tef`](tef-codes.md) | The transaction cannot be applied to the server's current (in-progress) ledger or any later one. It may have already been applied, or the condition of the ledger makes it impossible to apply in the future. | +| Local error | [`tel`](tel-codes.md) | The `rippled` server had an error due to local conditions, such as high load. You may get a different response if you resubmit to a different server or at a different time. | +| Malformed transaction | [`tem`](tem-codes.md) | The transaction was not valid, due to improper syntax, conflicting options, a bad signature, or something else. | +| Retry | [`ter`](ter-codes.md) | The transaction could not be applied, but it could apply successfully in a future ledger. | +| Success | [`tes`](tes-success.md) | (Not an error) The transaction succeeded. This result only final in a validated ledger. | + +The `rippled` server automatically retries failed transactions. It is important not to assume that a transaction has completely failed based on a tentative failure result. A transaction may later succeed unless its success or failure is [final](../finality-of-results.md). + +**Warning:** Transactions' provisional result codes may differ than their final result. Transactions that provisionally succeeded may eventually fail and transactions that provisionally failed may eventually succeed. Transactions that provisionally failed may also eventually fail with a different code. See [finality of results](../finality-of-results.md) for how to know when a transaction's result is final. + +The distinction between a local error (`tel`) and a malformed transaction (`tem`) is a matter of protocol-level rules. For example, the protocol sets no limit on the maximum number of paths that can be included in a transaction. However, a server may define a finite limit of paths it can process. If two different servers are configured differently, then one of them may return a `tel` error for a transaction with many paths, while the other server could successfully process the transaction. If enough servers are able to process the transaction that it survives consensus, then it can still be included in a validated ledger. + +By contrast, a `tem` error implies that no server anywhere can apply the transaction, regardless of settings. Either the transaction breaks the rules of the protocol, it is unacceptably ambiguous, or it is completely nonsensical. The only way a malformed transaction could become valid is through changes in the protocol; for example, if a new feature is adopted, then transactions using that feature could be considered malformed by servers that are running older software which predates that feature. + + +## Immediate Response + +The response from the `submit` method contains a provisional result from the `rippled` server indicating what happened during local processing of the transaction. + +The response from `submit` contains the following fields: + +| Field | Value | Description | +|:------------------------|:---------------|:----------------------------------| +| `engine_result` | String | A code indicating the outcome of the transaction, such as `tecPATH_DRY`. | +| `engine_result_code` | Signed Integer | A number that corresponds to the `engine_result`. The exact values are subject to change without notice. | +| `engine_result_message` | String | A human-readable message explaining what happened. This message is intended for developers to diagnose problems, and is subject to change without notice. | + +If nothing went wrong when submitting and applying the transaction locally, the response looks like this: + +```js + "engine_result": "tesSUCCESS", + "engine_result_code": 0, + "engine_result_message": "The transaction was applied. Only final in a validated ledger." +``` + +**Note:** A successful result at this stage does not indicate that the transaction has completely succeeded; only that it was successfully applied to the provisional version of the ledger kept by the local server. Failed results at this stage are also provisional and may change. See [Finality of Results](../finality-of-results.md) for details. + + + \ No newline at end of file diff --git a/content/concepts/transactions/transaction-structure.md b/content/concepts/transactions/transaction-structure.md new file mode 100644 index 0000000000..81940dab4b --- /dev/null +++ b/content/concepts/transactions/transaction-structure.md @@ -0,0 +1,151 @@ +--- +html: transaction-structure.html +parent: transactions.html +blurb: Transactions allow accounts to modify the XRP Ledger. +labels: + - Ledgers +--- +# Transaction Structure + +All transactions follow a similar structure. If you understand how to send one type of transaction, other transactions make sense as well. + +The type of a transaction (`TransactionType` field) is the most fundamental information about a transaction. This indicates what type of operation the transaction is supposed to do. + +Each transaction type has a set of common fields, coupled with additional fields relevant to the type of action it causes. + +## Transaction Common Fields + +Every transaction has the same set of common fields, plus additional fields based on the transaction type. Field names are case-sensitive. The common fields for all transactions are: + +| Field | JSON Type | [Internal Type][] | Description | +|:---------------------|:-----------------|:------------------|:-----------------| +| `Account` | String | AccountID | _(Required)_ The unique address of the [account](../accounts/accounts.md) that initiated the transaction. | +| `TransactionType` | String | UInt16 | _(Required)_ The type of transaction. Valid types include: `Payment`, `OfferCreate`, `OfferCancel`, `TrustSet`, `AccountSet`, `AccountDelete`, `SetRegularKey`, `SignerListSet`, `EscrowCreate`, `EscrowFinish`, `EscrowCancel`, `PaymentChannelCreate`, `PaymentChannelFund`, `PaymentChannelClaim`, and `DepositPreauth`. | +| `Fee` | String | Amount | _(Required; [auto-fillable][])_ Integer amount of XRP, in drops, to be destroyed as a cost for distributing this transaction to the network. Some transaction types have different minimum requirements.| +| `Sequence` | Number | UInt32 | _(Required; [auto-fillable][])_ The [sequence number](../../../../references/protocol-reference/data-types/basic-data-types.html#account-sequence) of the account sending the transaction. A transaction is only valid if the `Sequence` number is exactly 1 greater than the previous transaction from the same account. The special case `0` means the transaction is using a [Ticket](tickets.html) instead _(Added by the TicketBatch amendment.)_. | +| [`AccountTxnID`](#accounttxnid) | String | Hash256 | _(Optional)_ Hash value identifying another transaction. If provided, this transaction is only valid if the sending account's previously-sent transaction matches the provided hash. | +| [`Flags`](#flags-field) | Number | UInt32 | _(Optional)_ Set of bit-flags for this transaction. | +| `LastLedgerSequence` | Number | UInt32 | _(Optional; strongly recommended)_ Highest ledger index this transaction can appear in. Specifying this field places a strict upper limit on how long the transaction can wait to be validated or rejected. | +| [`Memos`](#memos-field) | Array of Objects | Array | _(Optional)_ Additional arbitrary information used to identify this transaction. | +| [`Signers`](#signers-field) | Array | Array | _(Optional)_ Array of objects that represent a [multi-signature](multi-signing.html) which authorizes this transaction. | +| `SourceTag` | Number | UInt32 | _(Optional)_ Arbitrary integer used to identify the reason for this payment, or a sender on whose behalf this transaction is made. Conventionally, a refund should specify the initial payment's `SourceTag` as the refund payment's `DestinationTag`. | +| `SigningPubKey` | String | Blob | _(Automatically added when signing)_ Hex representation of the public key that corresponds to the private key used to sign this transaction. If an empty string, indicates a multi-signature is present in the `Signers` field instead. | +| `TicketSequence` | Number | UInt32 | _(Optional)_ The sequence number of the [ticket](tickets.html) to use in place of a `Sequence` number. If this is provided, `Sequence` must be `0`. Cannot be used with `AccountTxnID`. | +| `TxnSignature` | String | Blob | _(Automatically added when signing)_ The signature that verifies this transaction as originating from the account it says it is from. | + +[auto-fillable]: #auto-fillable-fields + +Removed in: rippled 0.28.0: The `PreviousTxnID` field of transactions was replaced by the [`AccountTxnID`](#accounttxnid) field. This String / Hash256 field is present in some historical transactions. This is unrelated to the field also named `PreviousTxnID` in some [ledger objects](../../../../references/protocol-reference/ledger-data/ledger-data-formats.md). + + +## AccountTxnID + +The `AccountTxnID` field lets you chain your transactions together, so that a current transaction is not valid unless the previous transaction sent from the same account has a specific transaction hash. + +Unlike the `PreviousTxnID` field, which tracks the last transaction to _modify_ an account (regardless of sender), the `AccountTxnID` tracks the last transaction _sent by_ an account. To use `AccountTxnID`, you must first enable the [`asfAccountTxnID`](../../../../references/protocol-reference/transactions/transaction-types/accountset.md#accountset-flags) flag, so that the ledger keeps track of the ID for the account's previous transaction. (`PreviousTxnID`, by comparison, is always tracked.) + +One situation in which this is useful is if you have a primary system for submitting transactions and a passive backup system. If the passive backup system becomes disconnected from the primary, but the primary is not fully dead, and they both begin operating at the same time, you could potentially have serious problems like some transactions sending twice and others not at all. Chaining your transactions together with `AccountTxnID` ensures that, even if both systems are active, only one of them can submit valid transactions at a time. + +The `AccountTxnID` field cannot be used on transactions that use [Tickets](tickets.html). Transactions that use `AccountTxnID` cannot be placed in the [transaction queue](../server/transaction-queue.html). + + + +## Auto-fillable Fields + +Some fields can be automatically filled in before a transaction is signed, either by a `rippled` server or by a [client library](../../../references/client-libraries.md). Auto-filling values requires an active connection to the XRP Ledger to get the latest state, so it cannot be done offline. The details can vary by library, but auto-filling always provides suitable values for at least the following fields: + +* `Fee` - Automatically fill in the `Transaction Cost` based on the network. + + **Note:** When using `rippled`'s `sign` command, you can limit the maximum possible auto-filled value, using the `fee_mult_max` and `fee_mult_div` parameters.) + +* `Sequence` - Automatically use the next sequence number for the account sending the transaction. + +For a production system, we recommend _not_ leaving these fields to be filled by the server. For example, if transaction costs become high due to a temporary spike in network load, you may want to wait for the cost to decrease before sending some transactions, instead of paying the temporarily-high cost. + +The [`Paths` field](../../../../references/protocol-reference/transactions/transaction-types/payment.md#paths) of the `Payment` transaction type can also be automatically filled in. + + +## Flags Field + +The `Flags` field can contain various options that affect how a transaction should behave. The options are represented as binary values that can be combined with bitwise-or operations to set multiple flags at once. + +To check whether a transaction has a given flag enabled, use the bitwise-and operator on the flag's value and the `Flags` field. A result of zero indicates the flag is disabled, and a result equal to the flag value indicates the flag is enabled. (Any other result indicates you performed the wrong operation.) + +Most flags only have meaning for a specific transaction type. The same bitwise value may be reused for flags on different transaction types, so it is important to pay attention to the `TransactionType` field when setting and reading flags. + +Bits that are not defined as flags MUST be 0. (The fix1543 amendment enforces this rule on some transaction types. Most transaction types enforce this rule by default.) + +### Global Flags + +The only flag that applies globally to all transactions is as follows: + +| Flag Name | Hex Value | Decimal Value | Description | +|:----------------------|:-----------|:--------------|:--------------------------| +| `tfFullyCanonicalSig` | `0x80000000` | 2147483648 | **DEPRECATED** No effect. (If the RequireFullyCanonicalSig amendment is not enabled, this flag enforces a [fully-canonical signature](transaction-malleability.md#alternate-secp256k1-signatures).) | + +When using the `sign` method (or `submit` method in "sign-and-submit" mode), `rippled` adds a `Flags` field with `tfFullyCanonicalSig` enabled unless the `Flags` field is already present. The `tfFullyCanonicalSig` flag is not automatically enabled if `Flags` is explicitly specified. The flag is not automatically enabled when using the `sign_for` method to add a signature to a multi-signed transaction. + +**Note:** The `tfFullyCanonicalSig` flag was used from 2014 until 2020 to protect against [transaction malleability](transaction-malleability.md) while maintaining compatibility with legacy signing software. The RequireFullyCanonicalSig amendment ended compatibility with such legacy software and made the protections the default for all transactions. If you are using a [parallel network](../networks/parallel-networks.md) that does not have RequireFullyCanonicalSig enabled, you should always enable the `tfFullyCanonicalSig` flag to protect against transaction malleability. + +### Flag Ranges + +A transaction's `Flags` field can contain flags that apply at different levels or contexts. Flags for each context are limited to the following ranges: + +| Range Name | Bit Mask | Description | +|:-----------------|:-------------|:-------------------------------------------| +| Universal Flags | `0xff000000` | Flags that apply equally to all transaction types. | +| Type-based Flags | `0x00ff0000` | Flags with different meanings depending on the [transaction type](transaction-types.md) that uses them. | +| Reserved Flags | `0x0000ffff` | Flags that are not currently defined. A transaction is only valid if these flags are disabled. | + +**Note:** The `AccountSet` transaction type has [its own non-bitwise flags](../../../../references/protocol-reference/transactions/transaction-types/accountset.html#accountset-flags), which serve a similar purpose to type-based flags. [Ledger objects](../../../../references/protocol-reference/ledger-data/ledger-object-types/ledger-object-types.md) also have a `Flags` field with different bitwise flag definitions. + + +## Memos Field + +The `Memos` field includes arbitrary messaging data with the transaction. It is presented as an array of objects. Each object has only one field, `Memo`, which in turn contains another object with *one or more* of the following fields: + +| Field | Type | [Internal Type][] | Description | +|:-------------|:-------|:------------------|:---------------------------------| +| `MemoData` | String | Blob | Arbitrary hex value, conventionally containing the content of the memo. | +| `MemoFormat` | String | Blob | Hex value representing characters allowed in URLs. Conventionally containing information on how the memo is encoded, for example as a [MIME type](http://www.iana.org/assignments/media-types/media-types.xhtml). | +| `MemoType` | String | Blob | Hex value representing characters allowed in URLs. Conventionally, a unique relation (according to [RFC 5988](http://tools.ietf.org/html/rfc5988#section-4)) that defines the format of this memo. | + +The `MemoType` and `MemoFormat` fields should only consist of the following characters: `ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~:/?#[]@!$&'()*+,;=%` + +The `Memos` field is limited to no more than 1 KB in size (when serialized in binary format). + +Example of a transaction with a Memos field: + +```json +{ + "TransactionType": "Payment", + "Account": "rMmTCjGFRWPz8S2zAUUoNVSQHxtRQD4eCx", + "Destination": "r3kmLJN5D28dHuH8vZNUZpMC43pEHpaocV", + "Memos": [ + { + "Memo": { + "MemoType": "687474703a2f2f6578616d706c652e636f6d2f6d656d6f2f67656e65726963", + "MemoData": "72656e74" + } + } + ], + "Amount": "1" +} +``` + + +## Signers Field + +The `Signers` field contains a [multi-signature](multi-signing.html), which has signatures from up to 8 key pairs, that together should authorize the transaction. The `Signers` list is an array of objects, each with one field, `Signer`. The `Signer` field has the following nested fields: + +| Field | Type | Internal Type | Description | +|:----------------|:-------|:------------------|:--------------------------------| +| `Account` | String | AccountID | The address associated with this signature, as it appears in the signer list. | +| `TxnSignature` | String | Blob | A signature for this transaction, verifiable using the `SigningPubKey`. | +| `SigningPubKey` | String | Blob | The public key used to create this signature. | + +The `SigningPubKey` must be a key that is associated with the `Account` address. If the referenced `Account` is a funded account in the ledger, then the `SigningPubKey` can be that account's current Regular Key if one is set. It could also be that account's Master Key, unless the [`lsfDisableMaster`](../../../../references/protocol-reference/ledger-data/ledger-object-types/accountroot.md#accountroot-flags) flag is enabled. If the referenced `Account` address is not a funded account in the ledger, then the `SigningPubKey` must be the master key associated with that address. + +Because signature verification is a compute-intensive task, multi-signed transactions cost additional XRP to relay to the network. Each signature included in the multi-signature increases the [transaction cost](transaction-cost.md) required for the transaction. For example, if the current minimum transaction cost to relay a transaction to the network is `10000` drops, then a multi-signed transaction with 3 entries in the `Signers` array would need a `Fee` value of at least `40000` drops to relay. + + diff --git a/content/concepts/transactions/transactions.md b/content/concepts/transactions/transactions.md new file mode 100644 index 0000000000..dba7c329c6 --- /dev/null +++ b/content/concepts/transactions/transactions.md @@ -0,0 +1,229 @@ +--- +html: transactions.html +parent: concepts.html +blurb: Transactions allow accounts to modify the XRP Ledger. +labels: + - Ledgers +--- +# Transactions + +_Transactions_ allow accounts to modify the XRP Ledger. + +Transactions can do more than transfer currency. In addition to supporting various payment types, transactions in the XRP Ledger can rotate cryptographic keys, manage other settings, and trade in the XRP Ledger's decentralized exchange. + +## Transaction Structure + +### Example Unsigned Transaction + +Here is an example of an unsigned `Payment` transaction in JSON: + +```json +{ + "TransactionType" : "Payment", + "Account" : "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", + "Destination" : "ra5nK24KXen9AHvsdFTKHSANinZseWnPcX", + "Amount" : { + "currency" : "USD", + "value" : "1", + "issuer" : "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn" + }, + "Fee": "12", + "Flags": 2147483648, + "Sequence": 2, +} +``` + +| Field Name | Description | +|-----------------|-------------| +| TransactionType | Send a Payment. | +| Account | The account sending the funds. | +| Destination | The account receiving the funds. | +| Amount | The amount and type of currency. | +| currency | Currency type to transfer. | +| value | Quantity of currency to transfer. | +| issuer | Account that originally issued the currency. | +| Fee | Transaction fee, in drops (millionths of one XRP). | +| Flags | Additional standard settings for the transaction. | +| Sequence | Unique sequence number for the transaction. | + +### Signing and Submitting Transactions + +Sending a transaction to the XRP Ledger involves several steps: + +1. Create an [unsigned transaction in JSON format](#example-unsigned-transaction). +2. Use one or more signatures to [authorize the transaction](#authorizing-transactions). +3. Submit a transaction to an XRP Ledger server (usually a [`rippled` instance](server-modes.html)). If the transaction is properly formed, the server provisionally applies the transaction to its current version of the ledger and relays the transaction to other members of the peer-to-peer network. +4. The [consensus process](consensus.html) determines which provisional transactions get included in the next validated ledger. +5. The servers apply those transactions to the previous ledger in a canonical order and share their results. +6. If enough trusted validators created the exact same ledger, that ledger is declared _validated_ and the results of the transactions in that ledger are immutable. + + + +### Example Executed Transaction Response with Metadata + +After a transaction has been executed, the XRP Ledger adds metadata to show the transaction's final outcome and all the changes that the transaction made to the shared state of the XRP Ledger. + + + +You can check a transaction's status using the API, for example using the `tx` command. + +The results of a transaction, including all its metadata, are not final until the transaction appears in a **validated** ledger. + +Example response from the `tx` command: + +```json +{ + "id": 6, + "status": "success", + "type": "response", + "result": { + "Account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", + "Amount": { + "currency": "USD", + "issuer": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", + "value": "1" + }, + "Destination": "ra5nK24KXen9AHvsdFTKHSANinZseWnPcX", + "Fee": "10", + "Flags": 2147483648, + "Sequence": 2, + "SigningPubKey": "03AB40A0490F9B7ED8DF29D246BF2D6269820A0EE7742ACDD457BEA7C7D0931EDB", + "TransactionType": "Payment", + "TxnSignature": "3045022100D64A32A506B86E880480CCB846EFA3F9665C9B11FDCA35D7124F53C486CC1D0402206EC8663308D91C928D1FDA498C3A2F8DD105211B9D90F4ECFD75172BAE733340", + "date": 455224610, + "hash": "33EA42FC7A06F062A7B843AF4DC7C0AB00D6644DFDF4C5D354A87C035813D321", + "inLedger": 7013674, + "ledger_index": 7013674, + "meta": { + "AffectedNodes": [ + { + "ModifiedNode": { + "FinalFields": { + "Account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", + "Balance": "99999980", + "Flags": 0, + "OwnerCount": 0, + "Sequence": 3 + }, + "LedgerEntryType": "AccountRoot", + "LedgerIndex": "13F1A95D7AAB7108D5CE7EEAF504B2894B8C674E6D68499076441C4837282BF8", + "PreviousFields": { + "Balance": "99999990", + "Sequence": 2 + }, + "PreviousTxnID": "7BF105CFE4EFE78ADB63FE4E03A851440551FE189FD4B51CAAD9279C9F534F0E", + "PreviousTxnLgrSeq": 6979192 + } + }, + { + "ModifiedNode": { + "FinalFields": { + "Balance": { + "currency": "USD", + "issuer": "rrrrrrrrrrrrrrrrrrrrBZbvji", + "value": "2" + }, + "Flags": 65536, + "HighLimit": { + "currency": "USD", + "issuer": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", + "value": "0" + }, + "HighNode": "0000000000000000", + "LowLimit": { + "currency": "USD", + "issuer": "ra5nK24KXen9AHvsdFTKHSANinZseWnPcX", + "value": "100" + }, + "LowNode": "0000000000000000" + }, + "LedgerEntryType": "RippleState", + "LedgerIndex": "96D2F43BA7AE7193EC59E5E7DDB26A9D786AB1F7C580E030E7D2FF5233DA01E9", + "PreviousFields": { + "Balance": { + "currency": "USD", + "issuer": "rrrrrrrrrrrrrrrrrrrrBZbvji", + "value": "1" + } + }, + "PreviousTxnID": "7BF105CFE4EFE78ADB63FE4E03A851440551FE189FD4B51CAAD9279C9F534F0E", + "PreviousTxnLgrSeq": 6979192 + } + } + ], + "TransactionIndex": 0, + "TransactionResult": "tesSUCCESS" + }, + "validated": true + } +} +``` + +## Identifying Transactions + +Every signed transaction has a unique `"hash"` that identifies it. The server provides the hash in the response when you submit the transaction; you can also look up a transaction in an account's transaction history with the `account_tx` command. + +The transaction hash can be used as a "proof of payment," since anyone can look up the transaction by its hash to verify its final status. + + + + + + +## Claimed Cost Justification + +Although it might seem unfair to charge a [transaction cost](transaction-cost.md) for a failed transaction, the `tec` class of errors exists for good reasons: + +* Transactions submitted after the failed one do not have to have their Sequence values renumbered. Incorporating the failed transaction into a ledger uses up the transaction's sequence number, preserving the expected sequence. +* Distributing the transaction throughout the network increases network load. Enforcing a cost makes it harder for attackers to abuse the network with failed transactions. +* The transaction cost is generally very small in real-world value, so it should not harm users unless they are sending large quantities of transactions. + +## Authorizing Transactions + +In the decentralized XRP Ledger, a digital signature proves that a transaction is authorized to do a specific set of actions. Only signed transactions can be submitted to the network and included in a validated ledger. A signed transaction is immutable: its contents cannot change, and the signature is not valid for any other transaction. + +Transactions are authorized by any of the following signature types: + +* A single signature from the master private key that is mathematically associated with the sending address. You can disable or enable the master key pair using an `AccountSet` transaction. +* A single signature that matches the regular private key associated with the address. You can add, remove, or replace a regular key pair using a `SetRegularKey` transaction. +* A [multi-signature](multi-signing.md) that matches a list of signers owned by the address. You can add, remove, or replace a list of signers using a `SignerListSet` transaction. + +Any signature type can authorize any type of transaction, with the following exceptions: + +* Only the master private key can disable the master public key. +* Only the master private key can permanently give up the ability to freeze. +* You can never remove the last method of signing transactions from an address. + + + +For more information about master and regular key pairs, see [Cryptographic Keys](../accounts/cryptographic-keys.md). + + + + + diff --git a/content/concepts/transactions/trust-lines-and-issuing.md b/content/concepts/transactions/trust-lines-and-issuing.md new file mode 100644 index 0000000000..2aa714d594 --- /dev/null +++ b/content/concepts/transactions/trust-lines-and-issuing.md @@ -0,0 +1,88 @@ +--- +html: trust-lines-and-issuing.html +parent: transactions.html +blurb: Transactions allow accounts to modify the XRP Ledger. +labels: + - Transactions +--- + +# Trust Lines and Issuing + +Trust lines are structures in the XRP Ledger for holding [tokens](../tokens/tokens.md). Trust lines enforce the XRP Ledger's rule that you cannot cause someone else to hold a token they don't want. This precaution is necessary to enable the XRP Ledger's use case for [community credit](../tokens/tokens.md#community-credit) among other benefits. + +Each "trust line" is a _bidirectional_ relationship consisting of: + +- The identifiers for the **two [accounts](../accounts/accounts.md)** that the trust line connects. +- A single, shared **balance**, which is positive from the perspective of one account and negative from the other perspective. + - The account with a negative balance is generally considered the "issuer" of the tokens. However, in the APIs, the name `issuer` can refer to either side. +- Various **settings** and metadata. _Each_ of the two accounts can control its own settings on the trust line. + - Most importantly, each side sets a **limit** on the trust line, which is 0 by default. Each account's balance (from its perspective on the trust line) can't go above that account's limit, except [through that account's own actions](#going-below-the-limit). + +Each trust line is specific to a given currency code. Two accounts can have any number of trust lines between them for different currency codes, but only one shared trust line for any particular currency code. + + +## Creation + +Any account can unilaterally "trust" another account to issue a token by sending a `TrustSet` transaction with a nonzero limit and their own settings. This creates a line with a zero balance, and sets the other side's settings to the default. + +Trust lines can be implicitly created by some transactions, such as when you buy a token in the decentralized exchange. In this case, the trust line uses entirely default settings. + + +## Going Below the Limit + +There are three cases where you can hold a balance that is _greater_ than your limit on that trust line: + +1. When you acquire more of that token through trading. +2. When you decrease the limit on a trust line that has a positive balance. +3. When you acquire more of that token by [cashing a Check](payments/checks.md). (_Requires the CheckCashMakesTrustLine amendment :not_enabled:_) + + +## Trust Line Settings + +In addition to the shared balance, each account has its own settings on the trust line, which consist of the following: + +- The **Limit**, a number from 0 to the maximum token amount. Payments and other accounts' actions cannot cause the trust line's balance (from this account's perspective) to go over the limit. The default is `0`. +- **Authorized**: A true/false value used with Authorized Trust Lines to allow the other side to hold tokens this account issues. The default is `false`. Once set to `true`, this cannot be changed back. +- **No Ripple**: A true/false value to control whether tokens can [ripple](../tokens/rippling.md) through this trust line. The default depends on the account's "Default Ripple" setting; for new accounts, "Default Ripple" is off which means that `true` is the default for No Ripple. Usually, issuers should allow rippling and non-issuers should disable rippling unless they are using trust lines for community credit. +- **Freeze**: A true/false value indicating whether an [individual freeze](../tokens/freezing-tokens.md#individual-freeze) is in effect on this trust line. The default is `false`. +- **Quality In** and **Quality Out** settings, which allow the account to value tokens issued by the other account on this trust line at less (or more) than face value. For example, if a stablecoin issuer charges a 3% fee for withdrawing tokens for the equivalent off-ledger assets, you could use these settings to value those tokens at 97% of face value. The default, `0`, represents face value. + + +## Reserves and Deletion + +Since a trust line occupies space in the ledger, [a trust line increases the XRP your account must hold in reserve](../accounts/reserves.md). Either or both accounts in the trust line may be charged the reserve for the trust line, depending on the status of the trust line: if any of your settings are not the default, or if you hold a positive balance, it counts as one item toward your owner reserve. + +Generally, this means that the account that created the trust line is responsible for the reserve and the issuer is not. + +Trust lines are automatically deleted if both sides' settings are in the default state and the balance is 0. This means that, to delete a trust line, you need to: + +1. Send a `TrustSet` transaction to set your settings to the defaults. +2. Offload any positive balance you have on the trust line. You could do this by sending a [payment](payments/cross-currency-payments.md), or by selling the currency in the decentralized exchange. + +If your balance is negative (you are the issuer) or the other side's settings are not in the default state, you cannot cause the trust line to be totally deleted, but you can make it so that it does not count towards your owner reserve by following the same steps. + +Since the **Authorized** setting cannot be turned off after it has been turned on, it does not count toward the trust line's default state. + +### Free Trust Lines +[[Source]](https://github.com/ripple/rippled/blob/72377e7bf25c4eaee5174186d2db3c6b4210946f/src/ripple/app/tx/impl/SetTrust.cpp#L148-L168) + +Since trust lines are a powerful feature of the XRP Ledger, there is a special feature to make an account's first two trust lines "free". + +When an account creates a new trust line, if the account owns at most 2 items in the ledger including the new line, the account's owner reserve is treated as zero instead of the normal amount. This allows the transaction to succeed even if the account does not hold enough XRP to meet the increased reserve requirement for owning objects in the ledger. + +When an account owns 3 or more objects in the ledger, the full owner reserve applies. + + \ No newline at end of file diff --git a/content/concepts/understanding-xrpl.md b/content/concepts/understanding-xrpl.md new file mode 100644 index 0000000000..7f306e9570 --- /dev/null +++ b/content/concepts/understanding-xrpl.md @@ -0,0 +1,19 @@ +# Understanding the XRP Ledger + +The XRP Ledger leverages block chain technology to provide a decentralized system for facilitating and recording transactions for items of value, known as tokens. Individuals and businesses conduct business on the XRP ledger using secure accounts. + +## [XRP Ledger Ecosystem](xrpl-ecosystem.html) + +Learn more about the inner workings of the XRP Ledger ecosystem. + +## [Transactions](transactions.html) + +Learn about the different types of transaction. + +## [Tokens](tokens.html) + +Learn about tokens that you can exchange on the XRP Ledger, including fungible and non-fungible tokens. + +## [Accounts](accounts.html) + +Learn details of the structure of accounts and how they can be configured for specific business purposes. \ No newline at end of file diff --git a/content/concepts/xrpl/consensus-principles-and-rules.md b/content/concepts/xrpl/consensus-principles-and-rules.md new file mode 100644 index 0000000000..3f164d7fe4 --- /dev/null +++ b/content/concepts/xrpl/consensus-principles-and-rules.md @@ -0,0 +1,105 @@ +--- +html: consensus-principles-and-rules.html +parent: consensus.html +blurb: The rules and principles of the consensus algorithm that allow users to transfer funds (including fiat currencies, digital currencies and other forms of value) across national boundaries as seamlessly as sending an email. +labels: + - Blockchain +--- +# Consensus Principles and Rules + + + +The XRP Ledger is a universal payment system enabling users to transfer funds across national boundaries as seamlessly as sending an email. Like other peer-to-peer payment networks such as Bitcoin, the XRP Ledger enables peer-to-peer transaction settlement across a decentralized network of computers. Unlike other digital currency protocols, the XRP Ledger allows users to denominate their transactions with any currency they prefer, including fiat currencies, digital currencies and other forms of value, in addition to XRP (the native asset of the XRP Ledger). + +The XRP Ledger's technology enables near real-time settlement (three to six seconds) and contains a decentralized exchange, where payments automatically use the cheapest currency trade orders available to bridge currencies. + +## How Consensus Works + +At the core, the XRP Ledger is a shared database that records information such as accounts, balances, and offers to trade assets. Signed instructions called "transactions" cause changes such as creating accounts, making payments, and trading assets. + +As a cryptographic system, the owners of XRP Ledger accounts are identified by _cryptographic identities_, which correspond to public/private key pairs. Transactions are authorized by cryptographic signatures matching these identities. Every server processes every transaction according to the same deterministic, known rules. Ultimately, the goal is for every server in the network to have a complete copy of the exact same ledger state, without needing a single central authority to arbitrate transactions. + +### Consensus Rules + +The primary role of consensus is for participants in the process to agree on which transactions are to be processed as a group to resolve the double spend problem. There are four reasons this agreement is easier to achieve than might be expected: + +1. If there is no reason a transaction should not be included in such a group of transactions, all honest participants agree to include it. If all participants already agree, consensus has no work to do. +2. If there is any reason at all a transaction should not be included in such a group of transactions, all honest participants are willing to exclude it. If the transaction is still valid, there is no reason not to include it in the next round, and they should all agree to include it then. +3. It is extremely rare for a participant to particularly care how the transactions were grouped. Agreement is easiest when everyone’s priority is reaching agreement and only challenging when there are diverging interests. +4. Deterministic rules can be used even to form the groupings, leading to disagreement only in edge cases. For example, if there are two conflicting transactions in a round, deterministic rules can be used to determine which is included in the next round. + +Every participant’s top priority is correctness. They must first enforce the rules to be sure nothing violates the integrity of the shared ledger. For example, a transaction that is not properly signed must never be processed (even if other participants want it to be processed). However, every honest participant’s second priority is agreement. A network with possible double spends has no utility at all, so every honest participant values agreement above everything but correctness. + +### Consensus Rounds + +A consensus round is an attempt to agree on a group of transactions so they can be processed. A consensus round starts with each participant who wishes to do so taking an initial position. This is the set of valid transactions they have seen. + +Participants then “avalanche” to consensus: If a particular transaction does not have majority support, participants agree to defer that transaction. If a particular transaction does have majority support, participants agree to include the transaction. Thus slight majorities rapidly become full support and slight minorities rapidly become universal rejection from the current round. + +To prevent consensus from stalling near 50% and to reduce the overlap required for reliable convergence, the required threshold to include a transaction increases over time. Initially, participants continue to agree to include a transaction if 50% or more of other participants agree. If participants disagree, they increase this threshold, first to 60% and then even higher, until all disputed transactions are removed from the current set. Any transactions removed this way are deferred to the next ledger version. + +When a participant sees a supermajority that agrees on the set of transactions to next be processed, it declares a consensus to have been reached. + +### Consensus Can Fail + +It is not practical to develop a consensus algorithm that never fails to achieve perfect consensus. To understand why, consider how the consensus process finishes. At some point, each participant must declare that a consensus has been reached and that some set of transactions is known to be the result of the process. This declaration commits that participant irrevocably to some particular set of transactions as the result of the consensus process. + +Some participant must do this first or no participant will ever do it, and they will never reach a consensus. Now, consider the participant that does this first. When this participant decides that consensus is finished, other participants have not yet made that decision. If they were incapable of changing the agreed set from their point of view, they would have already decided consensus was finished. So they must be still capable of changing their agreed set. + +In other words, for the consensus process to ever finish, some participant must declare that consensus has been reached on a set of transactions even though every other participant is theoretically still capable of changing the agreed upon set of transactions. + +Imagine a group of people in a room trying to agree which door they should use to exit. No matter how much the participants discuss, at some point, _someone_ has to be the first one to walk out of a door, even though the people behind that person could still change their minds and leave through the other door. + +The probability of this kind of failure can be made very low, but it cannot be reduced to zero. The engineering tradeoffs are such that driving this probability down below about one in a thousand makes consensus significantly slower, and less able to tolerate network and endpoint failures. + +### How the XRP Ledger Handles Consensus Failure + +After a consensus round completes, each participant applies the set of transactions that they believe were agreed to. This results in constructing what they believe the next state of the ledger should be. + +Participants that are also validators then publish a cryptographic fingerprint of this next ledger. We call this fingerprint a “validation vote”. If the consensus round succeeded, the vast majority of honest validators should be publishing the same fingerprint. + +Participants then collect these validation votes. From the validation votes, they can determine whether the previous consensus round resulted in a supermajority of participants agreeing on a set of transactions or not. + +Participants then find themselves in one of three cases, in order of probability: + +1. They built the same ledger a supermajority agreed to. In this case, they can consider that ledger fully validated and rely on its contents. +2. They built a different ledger than a supermajority agreed on. In this case, they must build and accept the supermajority ledger. This typically indicates that they declared a consensus early and many other participants changed after that. They must “jump” to the super-majority ledger to resume operation. +3. No supermajority is clear from the received validations. In this case, the previous consensus round was wasted and a new round must occur before any ledger can be validated. + +Of course, case 1 is the most common. Case 2 does no harm to the network whatsoever. A small percentage of the participants could even fall into case 2 every round, and the network would work with no issues. Even those participants can recognize that they did not build the same ledger as the supermajority, so they know not to report their results as final until they are in agreement with the supermajority. + +Case 3 results in the network losing a few seconds in which it could have made forward progress, but is extremely rare. In this case, the next consensus round is much less likely to fail because disagreements are resolved in the consensus process and only remaining disagreements can cause a failure. + +On rare occasions, the network as a whole fails to make forward progress for a few seconds. In exchange, average transaction confirmation times are low. + +## Philosophy + +One form of reliability is the ability of a system to provide results even under conditions where some components have failed, some participants are malicious, and so on. While this is important, there is another form of reliability that is much more important in cryptographic payment systems — the ability of a system to produce results that can be relied upon. That is, when a system reports a result to us as reliable, we should be able to rely on that result. + +Real-world systems, however, face operational conditions in which both kinds of reliability can be compromised. These include hardware failures, communication failures, and even dishonest participants. Part of the XRP Ledger's design philosophy is to detect conditions where the reliability of results are impaired and report them, rather than providing results that must not be relied on. + +The XRP Ledger's consensus algorithm provides a robust alternative to proof of work systems, without consuming computational resources needlessly. Byzantine failures are possible, and do happen, but the consequence is only minor delays. In all cases, the XRP Ledger's consensus algorithm reports results as reliable only when they in fact are. + + + + +{% include '_snippets/rippled-api-links.md' %} +{% include '_snippets/tx-type-links.md' %} +{% include '_snippets/rippled_versions.md' %} diff --git a/content/concepts/xrpl/consensus-protections.ja.md b/content/concepts/xrpl/consensus-protections.ja.md new file mode 100644 index 0000000000..d8dbdf748f --- /dev/null +++ b/content/concepts/xrpl/consensus-protections.ja.md @@ -0,0 +1,74 @@ +--- +html: consensus-protections.html +parent: consensus-network.html +blurb: Learn how the XRP Ledger Consensus Protocol is protected against various problems and attacks that may occur in a decentralized financial system. #TODO: translate +labels: + - ブロックチェーン +--- +# 攻撃および障害モードに対するコンセンサスの保護 + +XRP Ledgerコンセンサスプロトコルは、 _ビザンチンフォールトトレラント性_ のあるコンセンサスメカニズムです。つまり、あらゆる不適切な状況(参加者が信頼できないオープンネットワークを利用して通信している場合や、不正使用者が常にシステムを乗っ取ろうとしているかまたは中断しようとしている場合など)が発生しても動作するように設計されています。さらに、XRP Ledgerコンセンサスプロトコルの参加者が事前に判明していない場合や、時間の経過とともに変わる場合があります。 + +[ネットワークに求められる特性](intro-to-consensus.html#コンセンサスプロトコルの特性)を維持しつつ、トランザクションをタイミングよく承認する作業は複雑であり、また完璧なシステムを構築することは不可能です。XRP Ledgerコンセンサスプロトコルは、ほとんどの状況で機能し、機能できない状況では可能な限り安全に失敗するように設計されています。 + +このページでは、XRP Ledgerコンセンサスプロトコルのいくつかの課題のタイプとその対処について説明します。 + +## 個々のバリデータの不適切な動作 + +_バリデータ_ とは、新しいレジャーバージョンの決定プロセスにアクティブに参加するサーバーです。バリデータは、そのバリデータを信用するように設定されているサーバーにのみ影響を与えます(間接的な影響を含む)。一部バリデータの動作が不適切であってもコンセンサスを継続できます。このような不適切な動作には、以下のさまざまなケースがあります。 + +- 使用できないかまたは過負荷状態である。 +- ネットワークから部分的に切断されており、メッセージが遅延なしで届くのは一部の参加者に限られる。 +- 他のサーバーを欺くかまたはネットワークを停止する目的で意図的に動作している。 +- 外部要因(抑圧的な政府からの脅威など)からのプレッシャーによって不正に動作している。 +- バグまたは古いソフトウェアが原因で、わかりにくいメッセージまたは誤った形式のメッセージが偶発的に送信される。 + +一般に、信頼できるバリデータのうち、不適切に動作しているバリデータがごくわずか(約20%未満)である限り、特に問題なくコンセンサスを継続できます。(正確な割合とその計算については、最新の[コンセンサスに関する研究](consensus-research.html)を参照してください。) + +バリデータの約20%以上がアクセス不能であるか適切に動作していない場合、ネットワークはコンセンサスに達することができません。この間、新しいトランザクションを暫定的に処理できますが、新しいレジャーバージョンを検証できないため、これらのトランザクションの最終結果は未確定になります。このような状況では、XRP Ledgerが正常ではないことがただちに明らかになるため、待機するか、または信頼できるバリデータのセットを再設定するかを決定できる参加者からの人的介入が促されます。 + +無効なトランザクションを承認する唯一の方法は、80%以上の信頼できるバリデータがそのトランザクションを承認し、その結果に合意することです。(無効なトランザクションには、すでに使用された資金を送金するトランザクションや、ネットワークのルールに違反するトランザクションなどがあります。)つまり、信頼できるバリデータの過半数が _共謀する_ 必要があります。多数の信頼できるバリデータが世界各地域で異なる人々や企業により運用されている状況では、意図的にこれを達成することは非常に困難です。 + + +## ソフトウェアの脆弱性 + +あらゆるソフトウェアシステムと同様に、XRP Ledgerコンセンサスプロトコル、広く導入されているソフトウェアパッケージ、またはその依存関係の実装に伴うバグ(または意図的に悪意のあるコード)の問題には、真剣に取り組む必要があります。巧妙に作成された入力を取り込んだサーバーをクラッシュさせるだけのバグであっても、ネットワークの進捗を妨害する目的で悪用される可能性があります。Rippleではこのような脅威に対処するため、次のようなさまざまな対策を導入しています。 + +- [オープンソースコードベース](https://github.com/ripple/rippled/)。これにより、一般のユーザーが関連ソフトウェアをレビュー、コンパイルし、個別にテストできます。 +- 公式XRP Ledgerリポジトリのあらゆる変更のための綿密で堅固なコードレビュープロセス。 +- すべてのリリースと公式ソフトウェアパッケージへのRipple社員によるデジタル署名付与。 +- セキュリティの脆弱性と不安定さに関する定期的に委託された専門家レビュー。 +- 責任を持って脆弱性を公開したセキュリティ研究者に報奨金を授与する[Bug Bountyプログラム](https://ripple.com/bug-bounty/)。 + + +## シビル攻撃 + +_[シビル攻撃](https://en.wikipedia.org/wiki/Sybil_attack)_ とは、大量の偽IDを使ってネットワークのコントロールを試みる攻撃です。XRP Ledgerでは、シビル攻撃は多数のバリデータを操作して、他のバリデータにこれらのバリデータを信頼するように仕向ける形で攻撃をしかける可能性があります。このような攻撃は理論上は可能ですが、バリデータが信頼を得るには人間による介入が必要であるため、実際には非常に困難です。 + +攻撃者が操作する検証サーバーの数に関係なく、既存の参加者が攻撃者のバリデータを信頼しない限りは、これらの参加者が何を検証済みと判断するかについて、このようなサーバーが影響を及ぼすことはできません。その他のサーバーは、バリデータリストまたは明示的な設定によって信頼できると設定されたバリデータのみを信頼します。(デフォルトのバリデータリストの仕組みの概要については、[バリデータ重複要件](#バリデータ重複要件)を参照してください。) + +この信頼は自動的に形成されるものではありません。したがってシビル攻撃を成功させるには、ターゲットとなる人物や企業が、攻撃者のバリデータを信頼してXRP Ledgerサーバーを再設定するように仕向けるという難しい作業をこなさなければなりません。ある人物または企業がだまされてXRP Ledgerサーバーを再設定したとしても、自らの設定を変更していない他の人物や企業に対する影響は最小限となります。 + + +## 51%攻撃 + +「51%攻撃」とは、特定の当事者が全採掘能力または投票能力の50%を超える割合を支配しているブロックチェーンに対する攻撃です。(厳密には、50%を _わずかでも_ 超えていれば十分であるため、この攻撃の名前は多少間違っています。)XRP Ledgerは、コンセンサスメカニズムに採掘を採用していないため、51%攻撃に対し脆弱ではありません。これに最も類似するXRP Ledgerへの攻撃には[シビル攻撃](#シビル攻撃)がありますが、この攻撃を実際に実施することは困難です。 + + +## バリデータ重複要件 + +XRP Ledgerのすべての参加者が何を検証済みとみなすかについて合意するには、参加者はまず、他の参加者が選択したバリデータ群によく似た信頼できるバリデータ群を選択する必要があります。最悪のケースでは、重複が約90%未満のために一部の参加者間に不一致が生じる場合があります。このため、Rippleは推奨バリデータの署名付きリストを公開しています。このリストには、企業や業界、コミュニティが運用する信頼性が高く適切に管理されたサーバーが含まれます。 + +デフォルトでは、XRP LedgerサーバーはRippleが運用するバリデータリストサイトを使用するように設定されています。このサイトでは、Rippleが定期的に更新する推奨バリデータリスト(推奨 _ユニークノードリスト_ (UNL))が公開されています。このように設定されているサーバーは、最新バージョンのリストに含まれているすべてのバリデータを信頼します。これにより、同じリストを使用する他のサーバーと100%重複することが保証されます。デフォルトの設定には、サイトのコンテンツの真正性を検証する公開鍵が含まれています。サイトがダウンした場合、XRP Ledgerのピアツーピアネットワーク内のサーバー間でリストに対する署名済みの更新を直接中継できます。 + +技術的には、サーバーを実行している場合、各自のリストサイトを設定するかまたは信頼できるバリデータを個別に明示的に選択することができますが、これらを行うことは推奨されません。選択したバリデータ群と他のサーバーとの重複が十分ではない場合、サーバーはネットワークの他の部分と不一致になる可能性があり、サーバーが不一致の状態でアクションを実行すると資金を失う可能性があります。 + +コンセンサスプロトコルの設計を改善し、より多様性のあるバリデータリストを実現するための研究が進んでいます。詳細は、[コンセンサスの研究](consensus-research.html)ページを参照してください。 + + +## 関連項目 + +- コンセンサスの**入門レベルの概要**については、[コンセンサスについて](intro-to-consensus.html)を参照してください。 +- コンセンサスプロトコルの**詳細な説明**については、[コンセンサス](consensus.html)を参照してください。 +- コンセンサスプロトコルの**設計に関する決定と背景**については、[コンセンサスの原理とルール](consensus-principles-and-rules.html)を参照してください。 +- コンセンサスプロトコルの特性と制約に関する**学術研究**については、[コンセンサスの研究](consensus-research.html)を参照してください。 diff --git a/content/concepts/xrpl/consensus-protections.md b/content/concepts/xrpl/consensus-protections.md new file mode 100644 index 0000000000..6b29e726a5 --- /dev/null +++ b/content/concepts/xrpl/consensus-protections.md @@ -0,0 +1,67 @@ +--- +html: consensus-protections.html +parent: consensus.html +blurb: The XRP Ledger is designed to protect itself against both malicious actors and unexpected network errors. +labels: + - Ledgers +--- + +# Consensus Protections + +The XRP Ledger Consensus Protocol is a _byzantine fault tolerant_ consensus mechanism, which means it is designed to work even if all kinds of things can go wrong: participants depend on an unreliable open network to communicate, and malicious actors might be attempting to control or interrupt the system at any given time. On top of that, the set of participants in the XRP Ledger Consensus Protocol is not known in advance, and can change over time. + +Confirming transactions quickly while maintaining the desired properties of the network is a complex challenge. It is impossible to build a perfect system. The XRP Ledger Consensus Protocol is designed to work as well as it can in most situations, and to fail as gracefully as possible in the situations where it cannot. + +This page describes some of the types of challenges that the XRP Ledger Consensus Protocol faces and how it handles them. + +## Individual Validators Misbehaving + +_Validators_ are servers that actively contribute to the process of deciding each new ledger version. Validators only have an influence over servers configured to trust them (including indirectly). Consensus can continue even if some validators are misbehaving, including a large variety of failure cases, such as: + +- Being unavailable or overloaded. +- Being partially disconnected from the network, so their messages reach only a subset of participants without delay. +- Intentionally behaving with intent to defraud others or halt the network. +- Behaving maliciously as a result of pressure from outside factors, such as threats from an oppressive government. +- Accidentally sending confusing or malformed messages due to a bug or outdated software. + +In general, consensus can continue without problems as long as only a small percentage (less than about 20%) of trusted validators are misbehaving at a given time. (For the exact percentages and the math behind them, see the latest [Consensus Research](consensus-research.md).) + +If more than about 20% of validators are unreachable or not behaving properly, the network fails to reach a consensus. During this time, new transactions can be tentatively processed, but new ledger versions cannot be validated, so those transactions' final outcomes are not certain. In this situation, it would become immediately obvious that the XRP Ledger is unhealthy, prompting intervention from human participants who can decide whether to wait or reconfigure their set of trusted validators. + +The only way to confirm an invalid transaction would be to get at least 80% of trusted validators to approve of the transaction and agree on its exact outcome. (Invalid transactions include those spending money that has already been spent, or otherwise breaking the rules of the network.) In other words, a large majority of trusted validators would have to _collude_. With dozens of trusted validators run by different people and businesses in different parts of the world, this would be very difficult to achieve intentionally. + + +## Software Vulnerabilities + +As with any software system, bugs (or intentionally malicious code) in the implementation of the XRP Ledger Consensus Protocol, commonly deployed software packages, or their dependencies, are a problem to be taken seriously. Even bugs that cause a server to crash when it sees carefully crafted inputs can be abused to disrupt the progress of the network. Ripple takes precautions to address this threat in its reference implementations of XRP Ledger software, including: + +- An [open-source code base](https://github.com/ripple/rippled/), so any member of the public can review, compile, and independently test the relevant software. +- A thorough and robust code review process for all changes to the official XRP Ledger repositories. +- Digital signatures from Ripple employees on all releases and official software packages. +- Regularly-commissioned professional reviews for security vulnerabilities and insecurities. +- A [bug bounty program](https://ripple.com/bug-bounty/) that rewards security researchers who responsibly disclose vulnerabilities. + + +## Sybil Attacks + +A [Sybil attack](https://en.wikipedia.org/wiki/Sybil_attack) is an attempt to take control of a network using a large number of fake identities. In the XRP Ledger, a Sybil attack would take the form of running a large number of validators, then convincing others to trust those validators. This sort of attack is theoretically possible, but would be very difficult to do because human intervention is necessary for validators to become trusted. + +No matter how many validating servers a would-be attacker runs, those servers have no say on what the existing participants consider validated unless those participants choose to trust the attacker's validators. Other servers only listen to the validators they are configured to trust, either through a validator list or explicit configuration. (See [validator overlap requirements](#validator-overlap-requirements) for a summary of how the default validator list works.) + +This trust does not happen automatically, so performing a successful Sybil attack would involve the difficult work of convincing targeted humans and businesses to reconfigure their XRP Ledger servers to trust the attacker's validators. Even in the case that one individual entity was fooled into doing so, this would have a minimal impact on others who do not change their configurations. + + +## 51% Attack + +A "51% attack" is an attack on a blockchain system where one party controls more than 50% of all mining or voting power. (Technically, the attack is slightly misnamed because _any_ amount over 50% is enough.) The XRP Ledger is not vulnerable to a 51% attack because it does not use mining in its consensus mechanism. The next closest analogue for the XRP Ledger is a [Sybil attack](#sybil-attacks), which would also be difficult. + + +## Validator Overlap Requirements + +For all participants in the XRP Ledger to agree on what they consider validated, they must start by choosing a set of trusted validators that are fairly similar to the sets chosen by everyone else. In the worst case, less than about 90% overlap could cause some participants to diverge from each other. For that reason, Ripple publishes a signed list of recommended validators, including trustworthy and well-maintained servers run by the company, industry, and community. + +By default, XRP Ledger servers are configured to use a validator list site run by Ripple. The site provides a list of recommended validators (also known as a recommended _Unique Node List_, or UNL), which Ripple updates periodically. Servers configured this way trust all validators in the latest version of the list, which ensures 100% overlap with others also using the same list. The default configuration includes a public key that verifies the authenticity of the site's contents. In case the site goes down, servers in the XRP Ledger's peer-to-peer network can directly relay the signed updates to the list among themselves. + +Technically, if you run a server, you can configure your own list site or explicitly choose validators to trust on an individual basis, but Ripple does not recommended doing so. If your chosen set of validators does not have enough overlap with others, your server may diverge from the rest of the network, and you could lose money by taking action based on your server's divergent state. + +Research is ongoing to design an improved consensus protocol that allows more heterogeneous validator lists. For more information, see the [Consensus Research](consensus-research.md) page. \ No newline at end of file diff --git a/content/concepts/xrpl/consensus-research.md b/content/concepts/xrpl/consensus-research.md new file mode 100644 index 0000000000..5e10942daf --- /dev/null +++ b/content/concepts/xrpl/consensus-research.md @@ -0,0 +1,17 @@ +--- +html: consensus-research.html +parent: consensus.html +blurb: Ripple researches both the theoretical and the practical limits of the XRP Ledger's consensus protocols. +labels: + - Ledgers +--- + +# Consensus Research + +Ripple researches both the theoretical and the practical limits of the XRP Ledger's consensus protocols, and explores other ideas in the same space. The following table lists scholarly articles published by Ripple: + +| Date | Title | Authors | Summary | +|---|---|---|---| +| 2018-02-20 | [Cobalt: BFT Governance in Open Networks](https://arxiv.org/abs/1802.07240) | MacBrough | Introduces a novel atomic broadcast algorithm called Cobalt that allows more flexibility in consensus UNLs. | +| 2018-02-20 | [Analysis of the XRP Ledger Consensus Protocol](https://arxiv.org/abs/1802.07242) | Chase, MacBrough | A detailed and updated analysis of the XRP Ledger consensus algorithm and its safety and liveness properties. | +| 2014 | [The Ripple Protocol Consensus Algorithm](https://ripple.com/files/ripple_consensus_whitepaper.pdf) | Schwartz, Youngs, Britto | Introduces the consensus algorithm behind the XRP Ledger. | \ No newline at end of file diff --git a/content/concepts/xrpl/consensus-structure.ja.md b/content/concepts/xrpl/consensus-structure.ja.md new file mode 100644 index 0000000000..cb83c4f4d4 --- /dev/null +++ b/content/concepts/xrpl/consensus-structure.ja.md @@ -0,0 +1,216 @@ +--- +html: consensus.html +parent: consensus-network.html +blurb: XRP Ledgerにおけるコンセンサスの役割について理解を深めましょう。 +labels: + - ブロックチェーン +--- +# コンセンサス + +_著者: Dave Cohen、David Schwartz、Arthur Britto_ + +この記事では、XRP Ledgerの概要や格納される情報、[トランザクション](transaction-formats.html)によってレジャー(台帳)が変化する様子について説明します。 + +XRP Ledger上でアプリケーションを構築する場合は、XRP Ledger APIの動作や、その動作によってもたされる影響を知っておくために、このプロセスを理解することが重要です。 + + +## まえがき + +ピアツーピアサーバーのXRP Ledgerネットワークは世界で共有されている台帳であり、ここから、アプリケーションはこの台帳の内容の状態に関して信頼できる情報を得ることができます。この状態に関する情報には以下の内容が含まれます。 + +- 各[アカウント](accounts.html)の設定 +- XRPおよび[発行済み通貨](issued-currencies.html)の残高 +- 分散型取引所でのオファー(注文) +- ネットワーク設定(例: [トランザクションコスト](transaction-cost.html)と[準備金](reserves.html)の金額) +- タイムスタンプ + +レジャーバージョンに含まれるデータの詳細な技術説明については、[レジャーフォーマットのリファレンス](ledger-data-formats.html)を参照してください。 + +[![図1: XRP Ledgerの要素](img/anatomy-of-a-ledger-complete.ja.png)](img/anatomy-of-a-ledger-complete.ja.png) + +_図1: XRP Ledgerの要素_ + +XRP Ledgerでは、数秒ごとに新しいレジャーバージョンが作成されます。あるレジャーバージョンの内容にネットワークが同意すると、そのレジャーバージョンは _検証済み_ となり、その内容が変更されることはありません。それ以前の検証済みのレジャーバージョンによって、レジャー履歴が形成されます。検証済みの最新のレジャーも、少し前の時点のネットワークの状態を表しており、履歴の一部となります。現時点で、ネットワークは次のレジャーバージョンに適用されてファイナライズされる可能性のあるトランザクションを評価しています。この評価が行われている間、ネットワークには、検証前のレジャーバージョン候補が存在します。 + +[![図2: XRP Ledgerの履歴](img/ledger-history.ja.png)](img/ledger-history.ja.png) + +_図2: XRP Ledgerの履歴_ + +レジャーバージョンには2つの識別子があります。1つ目の識別子は、そのレジャーバージョンの _レジャーインデックス_ です。レジャーバージョンの番号は1つずつ増加します。例えば、現行のレジャーバージョンのレジャーインデックスが100の場合、1つ前はレジャーインデックス99、1つ後はレジャーインデックスは101です。もう1つの識別子は _レジャーハッシュ_ で、レジャーの内容のデジタル指紋を表します。 + +サーバーがレジャーに適用するトランザクションを提案するときに、内容がわずかに異なる複数の候補レジャーバージョンが作成される場合があります。このような候補レジャーバージョンでは、レジャーインデックスは同じですがレジャーハッシュが異なります。多くの候補のうち、検証済みとなるのは1つだけです。それ以外の候補レジャーバージョンはすべて、破棄されます。そのため、履歴内の各レジャーインデックスに対して存在する検証済みのレジャーハッシュは1つのみです。 + +レジャーに対するユーザーレベルの変更は、トランザクションによってなされます。[トランザクション](transaction-formats.html)の例としては、決済、アカウントの設定またはトラストラインの変更、取引のオファー(注文)などがあります。各トランザクションは、レジャーに対する1つ以上の変更を承認するものであり、アカウント所有者によって暗号署名されます。アカウントの変更を承認したり、レジャーのそれ以外の内容を変更したりするには、トランザクションだけが唯一の方法です。 + +各レジャーバージョンには、一連のトランザクションと、そのようなトランザクションに関するメタデータも含まれています。それらのトランザクションは、新しいレジャーバージョンを作成するために前のバージョンのレジャーに適用されたものです。メタデータには、レジャーの状態データに対する、トランザクションの影響が正確に記録されています。 + +[![図3: レジャーバージョンに適用されるトランザクション](img/ledger-changes.ja.png)](img/ledger-changes.ja.png) + +_図3: レジャーバージョンに適用されるトランザクション_ + +レジャーインスタンスに含まれる一連のトランザクションはそのレジャーに記録され、XRP Ledger履歴の監査を可能としています。レジャーN+1のアカウント残高がレジャーNのアカウント残高と異なる場合、レジャーN+1にはその変更の原因となったトランザクションが含まれます。 + +検証済みのレジャー内に出現するトランザクションは、レジャーの変更に成功したか、または要求されたアクションを実行せずに処理された可能性があります。成功したトランザクションには、要求された変更がレジャーに適用されたことを示す**tesSUCCESS** [結果コード](transaction-results.html)が含まれます。レジャー内の失敗したトランザクションには、**tec**クラスの結果コードが含まれます。1 + +レジャーに含まれるトランザクションでは必ず、[トランザクションコスト](transaction-cost.html)として一部のXRPが消却されます。この場合、**tes**コードまたは**tec**コードが含まれていたかどうかは関係ありません。消却するXRPの正確な量は、署名されたトランザクションの手順で定義されます。 + +**tes**クラスや**tec**クラスの結果コード以外に、**ter**クラス、**tef**クラス、および**tem**クラスのコードがあります。後者の3つは、APIの呼び出しによって返された暫定的な失敗を示します。レジャーには、**tes**および**tec**のコードのみ表示されます。レジャーに含まれていないトランザクションによって、レジャーの状態(XRP残高を含む)が影響を受けることはありませんが、暫定的に失敗したトランザクションが後で成功する可能性があります。 + +[`rippled` API](http-websocket-apis.html)を使用する場合、レジャーに含めるように提案された候補トランザクションと、検証済みのレジャーに含まれる検証済みのトランザクションをアプリケーションで区別する必要があります。検証済みのレジャー内にあるトランザクションの結果のみが不変です。検証済みのレジャーには、候補トランザクションが含まれる場合と含まれない場合があります。 + +重要: 一部の[`rippled` API](http-websocket-apis.html)では、候補トランザクションに基づき暫定的な結果が返されます2。アプリケーションで、トランザクションの最終的な結果を判断する目的で暫定的な結果を使用するのは望ましくありません。最終的にトランザクションが成功したことを確実に知る唯一の方法は、そのトランザクションが検証済みのレジャー内にあり、かつ、結果コードがtesSUCCESSになるまで、トランザクションの状況を確認することです。トランザクションが検証済みレジャー内にあるが、結果コードがそれ以外の場合、トランザクションの失敗を意味します。トランザクションの[`LastLedgerSequence`](transaction-common-fields.html)で指定されたレジャーが検証済みにもかかわらず、そのトランザクションがそのレジャーまたはそれ以前の他のレジャー内にない場合、トランザクションは失敗しており、どのレジャーにも表示されません。検証済みのレジャー内に表示されるトランザクションの場合にのみ、結果は最終的なものとなります。それ以外の場合、このドキュメントで後述するように、`LastLedgerSequence`の制限により、表示されることはありません。 + +## XRP Ledgerプロトコル - コンセンサスと検証 + +ピアツーピアのXRP Ledgerネットワークは、トランザクションを承認して処理する多数の独立したXRP Ledgerサーバー(通常、[`rippled`](xrpl-servers.html)を実行)で構成されています。クライアントアプリケーションは、トランザクションに署名してXRP Ledgerサーバーに送信します。サーバーは、これらの候補トランザクションを処理するためにネットワーク内を中継します。クライアントアプリケーションには、モバイルおよびウェブウォレット、金融機関へのゲートウェイ、電子取引プラットフォームなどがあります。 + +[![図4: XRP Ledgerプロトコルの参加者](img/xrp-ledger-network.ja.png)](img/xrp-ledger-network.ja.png) + +_図4: XRP Ledgerプロトコルの参加者_ + +トランザクションを受信、中継、処理するサーバーは、追跡サーバーとバリデータのいずれかです。追跡サーバーの主な機能には、クライアントからのトランザクションの分散やレジャーに関する照会への応答が含まれます。検証サーバーは、追跡サーバーと同じ機能を実行し、さらにレジャー履歴を進めます3。 + +クライアントアプリケーションによって送信されたトランザクションを受け入れるときに、各追跡サーバーは最後に検証されたレジャーを開始点として使用します。受け入れられたトランザクションは候補トランザクションとなります。サーバーから候補トランザクションがそれぞれのピアに中継され、候補トランザクションがネットワーク全体に伝達されます。理想的には、各候補トランザクションはすべてのサーバーに伝達される必要があります。その結果、各サーバーは最後に検証されたレジャーに同じ一連のトランザクションを適用できる可能性が高くなります。しかし、トランザクションが伝達されるまでには時間がかかるため、サーバーは常に同じ候補トランザクションを処理するわけではありません。このことを考慮に入れて、XRP Ledgerでは、コンセンサスと呼ばれるプロセスを使用して、同一のトランザクションが処理され、ピアツーピアのXRP Ledgerネットワーク全体で検証済みのレジャーの一貫性が確保できるようにしています。 + +### コンセンサス + +ネットワーク内のサーバーは、候補トランザクションに関する情報を共有します。コンセンサスプロセスを通じて、バリデータは、候補トランザクションの特定のサブセットが次のレジャーで考慮されることに同意します。コンセンサスとは、サーバーが提案や一連の候補トランザクションを中継する反復プロセスです。サーバーは、選択されたバリデータの圧倒的多数4が同じ候補トランザクションのセットについて合意するまで、提案の通信と更新を行います。 + +コンセンサスの間、各サーバーは、そのサーバーの信頼できるバリデータ( _ユニークノードリスト(UNL)_ )と呼ばれる特定のサーバー群からの提案を評価します。5信頼できるバリデータとは、提案を評価するサーバーを欺こうと共謀しない、全体として「信頼できる」ネットワークのサブセットを表します。この「信頼」の定義では、選択された個々のバリデータが信頼されている必要はありません。バリデータの選択は、ネットワークに中継されたデータを改ざんする組織的な試みで共謀しないという想定に基づいて行われます6 + +[![図5: バリデータによるトランザクションセットの提案と修正](img/consensus-rounds.ja.png)](img/consensus-rounds.ja.png) + +_図5: バリデータによるトランザクションセットの提案と修正 - コンセンサスの開始時点で、バリデータ毎に異なるトランザクションセットを持っている可能性があります。後のラウンドで、サーバーは現在の提案を信頼できるバリデータの提案と一致するように変更します。このプロセスでは、現在議論しているレジャーバージョンに適用するトランザクションと、それ以降のレジャーバージョンに適用するトランザクションを決定します。_ + +合意済みの提案に含まれていない候補トランザクションは、その後も候補トランザクションとして残ります。これらは次のレジャーバージョンで再度検討される可能性があります。通常、1つのレジャーバージョンから除外されたトランザクションは、次のレジャーバージョンに含まれます。 + +状況によっては、いつまでもコンセンサスに達することができないトランザクションもあります。そのような状況として、ネットワークが、必要な[トランザクションコスト](transaction-cost.html)を、トランザクションで指定されたものよりも高い値に変更している場合が考えられます。将来のある時点でこの手数料が引き下げられると、そのトランザクションが成功する可能性があります。トランザクションの成功または失敗が一定時間内に確定するように、トランザクションが特定のレジャーインデックスによって一定時間処理されない場合は期限切れになるように設定することができます。詳細は、[信頼できるトランザクションの送信](reliable-transaction-submission.html)を参照してください。 + +### 検証 + +検証は、全体のコンセンサスプロセスの第2段階です。このプロセスでは、すべてのサーバーで同じ結果が得られたことを確認し、あるレジャーバージョンが最終バージョンとして宣言されます。まれに、第一段階の[コンセンサスプロセスが失敗する場合](consensus-principles-and-rules.html#コンセンサス失敗の可能性)があります。検証によって後で確認が行われるため、サーバーは結果を確認し、それに応じて対処することができます。 + +検証は、大きく分けて次の2つの部分に分かれます。 + +- 合意済みのトランザクションセットから結果として生じるレジャーバージョンを計算する。 +- 結果を比較し、十分に信頼できるバリデータが同意した場合はレジャーバージョンの検証済みを宣言する。 + +#### 検証の計算と共有 + +コンセンサスプロセスが完了すると、各サーバーは合意済みの一連のトランザクションから新しいレジャーを個別に計算します。各サーバーは、同じ規則に従って結果を次のように計算します。 + +1. 一つ前の検証済みのレジャーから始めます。 + +2. すべてのサーバーが同じ方法で処理できるように、合意済みのトランザクションセットを _正規順序_ で並べ変えます。 + + [正規順序](https://github.com/ripple/rippled/blob/8429dd67e60ba360da591bfa905b58a35638fda1/src/ripple/app/misc/CanonicalTXSet.cpp#L25-L36)は、トランザクションを受け取った順序ではありません(サーバーが同じトランザクションを異なる順序で受け取る可能性があるため)。参加者がトランザクションの順序付けで競合しないように、故意に操作するのが困難な正規順序を使います。 + +3. 指示に従って、各トランザクションを順番に処理します。それに応じてレジャーの状態データを更新します。 + + トランザクションを正常に実行できない場合は、[`tec`クラス結果コード](tec-codes.html)を持つトランザクションを含めます。1 + + 特定の「再試行可能な」トランザクションの失敗に対しては、同じレジャーバージョンの他のトランザクションが実行された後に再試行されるように、そのトランザクションを正規順序の最後に移動します。 + +4. 適切なメタデータでレジャーヘッダーを更新します。 + + これには、レジャーインデックス、前に検証済みのレジャーの識別ハッシュ(このレジャーの「親」)、このレジャーバージョンの予定終了時刻、このレジャーの内容の暗号化ハッシュなどのデータが含まれます。 + +5. 新しいレジャーバージョンの識別用ハッシュを計算します。 + +[![図7: XRP Ledgerサーバーでレジャー検証を計算する](img/consensus-calculate-validation.ja.png)](img/consensus-calculate-validation.ja.png) + +_図7: XRP Ledgerサーバーでレジャー検証を計算する - 各サーバーは、同意済みのトランザクションを前の検証済みレジャーに適用します。バリデータは結果をネットワーク全体に送信します。_ + +#### 結果を比較する + +バリデータはそれぞれ、計算したレジャーバージョンのハッシュを含む署名付きメッセージの形式で結果を中継します。 _検証_ と呼ばれるこれらのメッセージによって、各サーバーで計算したレジャーとそのピアのレジャーを比較することができます。 + +[![図8: 圧倒的多数のピアが同じ結果を計算するとレジャーが検証される](img/consensus-declare-validation.ja.png)](img/consensus-declare-validation.ja.png) + +_図8: 圧倒的多数のピアが同じ結果を計算するとレジャーが検証される - 各サーバーは、計算されたレジャーを、選択されたバリデータから受け取ったハッシュと比較します。一致しない場合、サーバーは正しいレジャーを再計算または取得する必要があります。_ + +ネットワーク内のサーバーは、圧倒的多数のピアが同じ検証ハッシュに署名してそれをブロードキャストしたときに、そのレジャーインスタンスを検証済みと認識します 7。それ以降のトランザクションは、レジャーインデックスN+1の更新および検証済みのこのレジャーに適用されます。 + +サーバーが少数で、ピアと異なるレジャーを計算した場合、計算したレジャーは無視されます8。正しいレジャーを再計算するか、必要に応じて正しいレジャーを取得します。 + +ネットワークで、検証に関する圧倒的多数の同意が得られない場合、コンセンサスプロセスで一貫した提案を作成するにはトランザクション量が多すぎるか、ネットワーク遅延が大きすぎることを意味します。この場合、サーバーはコンセンサスプロセスを繰り返します。コンセンサスが始まってから時間が経過するにつれて、各コンセンサスラウンドで不一致は減少するため、過半数のサーバーが同じ候補トランザクションのセットを受け取った可能性が高くなります。XRP Ledgerは、これらの状況に応じて[トランザクションコスト](transaction-cost.html)と、コンセンサスを待つ時間を動的に調整します。 + +検証について圧倒的多数の合意が得られると、サーバーは検証済みの新しいレジャー、レジャーインデックスN+1との作業に入ることができます。最後のラウンドに含まれなかった候補トランザクションと、その間に送信された新しいトランザクションに対して、コンセンサスと検証プロセスが繰り返されます9。 + + +## 要点 + +XRP Ledgerに送信されたトランザクションはすぐには処理されません。一定期間、各トランザクションは候補状態になります。 + +単一トランザクションのライフサイクルは次のとおりです。 + +- アカウント所有者によってトランザクションが作成され、署名されます。 +- トランザクションがネットワークに送信されます。 + - 書式が正しくないトランザクションはその場で拒否される可能性があります。 + - 書式が正しいトランザクションは暫定的に成功し、その後で失敗する可能性があります。 + - 書式が正しトランザクションは暫定的に失敗し、その後で成功する可能性があります。 +- コンセンサスの間、トランザクションはレジャーに含まれます。 + - コンセンサスラウンドが成功すると、レジャーが有効になります。 + - コンセンサスラウンドが失敗すると、成功するまでコンセンサスプロセスが繰り返されます。 +- 検証済みレジャーには、トランザクションとレジャーの状態への反映が含まれます。 + +アプリケーションでは、候補トランザクションの暫定的な結果ではなく、検証済みのレジャーの情報のみを信頼してください。一部の[`rippled` API](http-websocket-apis.html)では、トランザクションの暫定的な結果が最初に返されます。トランザクションの結果が不変になるのは、そのトランザクションが検証済みレジャーに含まれている場合か、トランザクションに`LastLedgerSequence`が含まれ、そのレジャーインデックス以下の検証済みレジャーに出現しない場合に限られます。 + +トランザクションを送信するアプリケーションのベストプラクティスは次のとおりです。 + +- `LastLedgerSequence`パラメーターを使用して、トランザクションが確定的かつ迅速な方法で検証されるか、失敗するようにします。 +- 検証されたレジャーでトランザクションの結果を確認します。 + - トランザクションを含むレジャーが検証されるか、`LastLedgerSequence`が経過するまで、結果は暫定的です。 + - 結果コードが**tesSUCCESS**で`"validated": true`のトランザクションは、恒久的に成功しています。 + - 結果コードがそれ以外の場合で`"validated": true`のトランザクションは、恒久的に失敗しています。 + - トランザクションの`LastLedgerSequence`によって識別された検証済みレジャーを含め、これまでの検証済みのレジャーに出現しないトランザクションは、恒久的に失敗しています。 + - このようなケースを検出するために、レジャーの継続的な履歴を有するサーバーを使用には注意してください10。 + - `LastLedgerSequence`で識別されるレジャーが検証されるまで、トランザクションの状態を繰り返し確認する必要がある場合があります。 + +## 関連項目 + +- **コンセプト:** + - [コンセンサスについて](intro-to-consensus.html) + - [コンセンサスの研究](consensus-research.html) + - [Rippleコンセンサスの動画](https://www.youtube.com/watch?v=pj1QVb1vlC0) +- **チュートリアル:** + - [信頼できるトランザクションの送信](reliable-transaction-submission.html) + - [バリデータとしての`rippled`の実行](run-rippled-as-a-validator.html) +- **リファレンス:** + - [レジャーフォーマットのリファレンス](ledger-data-formats.html) + - [トランザクションフォーマットのリファレンス](transaction-formats.html) + - [Consensus_infoメソッド][] + - [Validator_list_sitesメソッド][] + - [Validatorsメソッド][] + + + + + +## 脚注 + +1 – [**tec**結果コード](tec-codes.html)を持つトランザクションでは、リクエストされたアクションは実行されませんが、レジャーには影響します。ネットワークの悪用を防ぎ、トランザクションの分散コストを賄うために、XRPの[トランザクションコスト](transaction-cost.html)が消却されます。同じ送信者によって同時刻に送信された他のトランザクションをブロックしないようにするには、送信者のアカウントの[シーケンス番号](basic-data-types.html#アカウントシーケンス)を都度増やしてゆきます。`tec`クラスの結果を持つトランザクションは、期限切れのオブジェクトや資金のない取引注文を削除するなどのメンテナンスも行います。 + +2 – 例えば、Aliceが100ドルを持っていて、全額をBobに送信するシナリオを考えてみましょう。アプリケーションは最初にPaymentトランザクションを送信し、Aliceの残高を確認したらすぐにAPIから0ドルが返されます。この値は、候補トランザクションの暫定結果に基づいています。支払いが失敗し、Aliceの残高が100ドルのままになる(または他のトランザクションによって別の金額になる)場合があります。AliceからBobへの支払いが成功したことを確実に知る唯一の方法は、そのトランザクションが検証済みのレジャー内にあり、かつ結果コードが**tesSUCCESS**になるまで、トランザクションの状況を確認することです。トランザクションが検証済みレジャーにあるが、結果コードが異なる場合、支払いは失敗したことを意味します。 + +3 – 厳密に言えば、バリデータは追跡サーバーのサブセットです。同じ機能を提供することに加えて、「検証」メッセージを送信します。追跡サーバーは、レジャー履歴全体を保持しているか、部分的なレジャー履歴を保持しているかによって、さらに分類することができます。 + +4 – トランザクションを認識したピアの割合(%)がしきい値を下回った場合、コンセンサスのラウンドは失敗します。各ラウンドは反復プロセスです。第1ラウンドの開始時には、少なくともピアの50%が同意する必要があります。コンセンサスラウンドの最終的なしきい値は80%の合意です。これらの具体的な値は変更される可能性があります。 + +5 – 各サーバーは独自の信頼できるバリデータを定義しますが、ネットワークの一貫性は、様々なサーバーで重複の度合いが高いバリデータのリストが選択されるかどうかにかかっています。このため、Rippleでは推奨するバリデータのリストを公開しています。 + +6 – 共謀しないとされるバリデータからだけでなくすべてのバリデータからの提案が評価される場合は、悪意のある攻撃者によって、無効なトランザクションが導入されたり、提案から有効なトランザクションが除外されたりする可能性があります。選択されたバリデータリストによって、[シビル攻撃](consensus-protections.html#シビル攻撃)から保護することができます。 + +7 – 2014年11月の時点で、圧倒的多数を表すしきい値として、少なくともピアの80%が検証すべきレジャーに同意する必要があります。これは、コンセンサスのラウンドで要求される割合と同じです。いずれのしきい値も変更される可能性があり、同じである必要はありません。 + +8 – 実際には、サーバーは自身が少数であることを検知してから、すべてのピアの検証を受け取ります。ピアの20%以上から不一致の検証を受け取ると、その検証がしきい値の80%を満たしていないことが分かります。その時点で、レジャーの再計算を始めることができます。 + +9 – 実際には、効率的に実行できるように、検証の完了前に新しいコンセンサスのラウンドが開始されます。 + +10 – `rippled`サーバーはレジャーの履歴全体がなくてもAPIリクエストに応答することができます。サービスやネットワーク接続が中断すると、そのサーバーのレジャー履歴にレジャーの不足や誤差が生じることがあります。時間の経過とともに、`rippled`によってその誤差は埋まります(そのように設定されている場合)。欠落しているトランザクションを検証する場合は、トランザクションが送信されてからLastLedgerSequenceまでの連続した完全なレジャーを持つサーバーに照らして検証することが重要です。特定のサーバーで利用できるcomplete_ledgersを判断するには、RPCサーバーの状態を使用します。 + + + +{% include '_snippets/rippled-api-links.md' %} +{% include '_snippets/tx-type-links.md' %} +{% include '_snippets/rippled_versions.md' %} diff --git a/content/concepts/xrpl/consensus-structure.md b/content/concepts/xrpl/consensus-structure.md new file mode 100644 index 0000000000..a81a73204c --- /dev/null +++ b/content/concepts/xrpl/consensus-structure.md @@ -0,0 +1,220 @@ +--- +html: consensus-structure.html +parent: consensus.html +blurb: Understand the design decisions for consensus in the XRP Ledger. +labels: + - Blockchain +--- + +# Consensus Structure + +_Written by Dave Cohen, David Schwartz, and Arthur Britto._ + +This article provides a high level overview of the XRP Ledger, the information it stores, and how [transactions](transaction-formats.html) result in changes to the ledger. + +When building applications on the XRP Ledger, it is important to understand this process, so as not to be surprised by the behavior of XRP Ledger APIs and their effects. + + +## Introduction + +The peer-to-peer XRP Ledger network provides a worldwide, shared ledger, which gives applications authoritative information about the state of its contents. This state information includes: + +- settings for each [account](accounts.html) +- balances of XRP and [tokens](tokens.html) +- offers in the distributed exchange +- network settings, such as [transaction costs](transaction-cost.html) and [reserve](reserves.html) amounts +- a timestamp + +For a full, technical description of which data is included in a ledger version, see the [Ledger Format Reference](ledger-data-formats.html). + +{{ include_svg("img/anatomy-of-a-ledger-complete.svg", "Figure 1: XRP Ledger Elements") }} + +_Figure 1: XRP Ledger Elements_ + +The XRP Ledger has a new ledger version every several seconds. When the network agrees on the contents of a ledger version, that ledger version is _validated_, and its contents can never change. The validated ledger versions that preceded it form the ledger history. Even the most recent validated ledger is part of history, as it represents the state of the network as of a short time ago. In the present, the network is evaluating transactions which may be applied and finalized in the next ledger version. While this evaluation is happening, the network has candidate ledger versions that are not yet validated. + +{{ include_svg("img/ledger-history.svg", "Figure 2: XRP Ledger History")}} + +_Figure 2: XRP Ledger History_ + +A ledger version has two identifiers. One identifier is its _ledger index_. Ledger versions are numbered incrementally. For example, if the current ledger version has ledger index of 100, the previous has ledger index 99 and the next has ledger index 101. The other identifier is a _ledger hash_, which is a digital fingerprint of the ledger's contents. + +As servers propose transactions to apply to the ledger, they may create several candidate ledger versions with slightly different contents. These candidate ledger versions have the same ledger index but different ledger hashes. Of the many candidates, only one can become validated. All the other candidate ledger versions are discarded. Thus, there is exactly one validated ledger hash for each ledger index in history. + +User level changes to the ledger are the results of transactions. Examples of [transactions](transaction-formats.html) include payments, changes to account settings or trust lines, and offers to trade. Each transaction authorizes one or more changes to the ledger, and is cryptographically signed by an account owner. Transactions are the only way to authorize changes to an account, or to change anything else in the ledger. + +Each ledger version also contains a set of transactions and metadata about those transactions. The transactions it includes are only the ones that have been applied to the previous ledger version to create the new ledger version. The metadata records the exact effects of the transaction on the ledger's state data. + +{{ include_svg("img/ledger-changes.svg", "Figure 3: Transactions Applied to Ledger Version")}} + +_Figure 3: Transactions Applied to Ledger Version_ + +The set of transactions included in a ledger instance are recorded in that ledger and allow audits of the XRP Ledger history. If an account balance is different in ledger N+1 than it was in ledger N, then ledger N+1 contains the transaction(s) responsible for the change. + +Transactions that appear in a validated ledger may have succeeded in changing the ledger, or may have been processed without doing the requested action. Successful transactions have the **`tesSUCCESS`** [result code](transaction-results.html) which indicates the requested changes are applied to the ledger. Failed transactions in the ledger have **`tec`** class result codes.1 + +All transactions included in a ledger destroy some XRP as a [transaction cost](transaction-cost.html), regardless of whether they had a **`tes`** or **`tec`** code. The exact amount of XRP to destroy is defined by the signed transaction instructions. + +There are other classes of result codes besides **`tes`** and **`tec`**. Any other classes of result code indicate provisional failures returned by API calls. Only **`tes`** and **`tec`** codes appear in ledgers. Transactions that are not included in ledgers cannot have any effect on the ledger state (including XRP balances), but transitions that provisionally failed may still end up succeeding. + +When working with [XRP Ledger APIs](http-websocket-apis.html), applications must distinguish between candidate transactions proposed for inclusion in a ledger versus validated transactions which are included in a validated ledger. Only transaction results found in a validated ledger are immutable. A candidate transaction may eventually be included in a validated ledger, or it may not. + +Important: Some [`rippled` APIs](http-websocket-apis.html) provide provisional results, based on candidate transactions 2. Applications should never rely on provisional results to determine the final outcome of a transaction. The only way to know with certainty that a transaction finally succeeded is to check the status of the transaction until it is both in a validated ledger and has result code `tesSUCCESS`. If the transaction is in a validated ledger with any other result code, it has failed. If the ledger specified in a transaction’s [`LastLedgerSequence`](transaction-common-fields.html) has been validated, yet the transaction does not appear in that ledger or any before it, then that transaction has failed and can never appear in any ledger. An outcome is final only for transactions that appear in a validated ledger or can never appear because of `LastLedgerSequence` restrictions as explained later in this document. + +## The XRP Ledger Protocol – Consensus and Validation + +The peer-to-peer XRP Ledger network consists of many independent XRP Ledger servers (typically running [`rippled`](xrpl-servers.html)) that accept and process transactions. Client applications sign and send transactions to XRP Ledger servers, which relay these candidate transactions throughout the network for processing. Examples of client applications include mobile and web wallets, gateways to financial institutions, and electronic trading platforms. + +{{ include_svg("img/xrp-ledger-network.svg", "Figure 4: Participants in the XRP Ledger Protocol") }} + +_Figure 4: Participants in the XRP Ledger Protocol_ + +The servers that receive, relay and process transactions may be either tracking servers or validators. The major functions of tracking servers include distributing transactions from clients and responding to queries about the ledger. Validating servers perform the same functions as tracking servers and also contribute to advancing the ledger history. 3. + +While accepting transactions submitted by client applications, each tracking server uses the last validated ledger as a starting point. The accepted transactions are candidates. The servers relay their candidate transactions to their peers, allowing the candidate transactions to propagate throughout the network. Ideally, each candidate transaction would be known to all servers, allowing each to consider the same set of transactions to apply to the last validated ledger. As transactions take time to propagate however, the servers do not work with the same set of candidate transactions at all times. To account for this, the XRP Ledger uses a process called consensus to ensure that the same transactions are processed and validated ledgers are consistent across the peer-to-peer XRP Ledger network. + +### Consensus + +The servers on the network share information about candidate transactions. Through the consensus process, validators agree on a specific subset of the candidate transactions to be considered for the next ledger. Consensus is an iterative process in which servers relay proposals, or sets of candidate transactions. Servers communicate and update proposals until a supermajority 4 of chosen validators agree on the same set of candidate transactions. + +During consensus, each server evaluates proposals from a specific set of servers, known as that server's trusted validators, or _Unique Node List (UNL)_.5 Trusted validators represent a subset of the network which, when taken collectively, is "trusted" not to collude in an attempt to defraud the server evaluating the proposals. This definition of "trust" does not require that each individual chosen validator is trusted. Rather, validators are chosen based on the expectation they will not collude in a coordinated effort to falsify data relayed to the network 6. + +{{ include_svg("img/consensus-rounds.svg", "Figure 5: Validators Propose and Revise Transaction Sets") }} + +_Figure 5: Validators Propose and Revise Transaction Sets — At the start of consensus, validators may have different sets of transactions. In later rounds, servers modify their proposals to match what their trusted validators proposed. This process determines which transactions they should apply to the ledger version currently being discussed, and which they should postpone for later ledger versions._ + +Candidate transactions that are not included in the agreed-upon proposal remain candidate transactions. They may be considered again in for the next ledger version. Typically, a transaction which is omitted from one ledger version is included in the next ledger version. + +In some circumstances, a transaction could fail to achieve consensus indefinitely. One such circumstance is if the network increases the required [transaction cost](transaction-cost.html) to a value higher than the transaction provides. The transaction could potentially succeed if the fees are lowered at some point in the future. To ensure that a transaction either succeeds or fails within a limited amount of time, transactions can be set to expire if they are not processed by a certain ledger index. For more information, see [Reliable Transaction Submission](reliable-transaction-submission.html). + +### Validation + +Validation is the second stage of the overall consensus process, which verifies that the servers got the same results and declares a ledger version final. In rare cases, the first stage of [consensus can fail](consensus-principles-and-rules.html#consensus-can-fail); validation provides a confirmation afterward so that servers can recognize this and act accordingly. + +Validation can be broken up into roughly two parts: + +- Calculating the resulting ledger version from an agreed-upon transaction set. +- Comparing results and declaring the ledger version validated if enough trusted validators agree. + +Each server in the network performs validation separately and locally; the consensus process can proceed to tentatively confirm transactions even if no ledger is validated from a given round. + + +#### Calculate and Share Validations + +When the consensus process completes, each server independently computes a new ledger from the agreed-upon set of transactions. Each server calculates the results by following the same rules, which can be summarized as follows: + +1. Start with the previous validated ledger. + +2. Place the agreed-upon transaction set in _canonical order_ so that every server processes them the same way. + + [Canonical order](https://github.com/ripple/rippled/blob/8429dd67e60ba360da591bfa905b58a35638fda1/src/ripple/app/misc/CanonicalTXSet.cpp#L25-L36) is not the order the transactions were received, because servers may receive the same transactions in different order. To prevent participants from competing over transaction ordering, canonical order is hard to manipulate. + +3. Process each transaction according to its instructions, in order. Update the ledger's state data accordingly. + + If the transaction cannot be successfully executed, include the transaction with a [`tec`-class result code](tec-codes.html).1 + + For certain "retriable" transaction failures, instead move the transaction to the end of the canonical order to be retried after other transactions in the same ledger version have executed. + +4. Update the ledger header with the appropriate metadata. + + This includes data such as the ledger index, the identifying hash of the previous validated ledger (this one's "parent"), this ledger version's approximate close time, and the cryptographic hashes of this ledger's contents. + +5. Calculate the identifying hash of the new ledger version. + +{{ include_svg("img/consensus-calculate-validation.svg", "Figure 7: An XRP Ledger Server Calculates a Ledger Validation") }} + +_Figure 7: An XRP Ledger Server Calculates a Ledger Validation — Each server applies agreed-upon transactions to the previous validated ledger. Validators send their results to the entire network._ + +#### Compare Results + +Validators each relay their results in the form of a signed message containing the hash of the ledger version they calculated. These messages, called _validations_, allow each server to compare the ledger it computed with those of its peers. + +{{ include_svg("img/consensus-declare-validation.svg", "Figure 8: Ledger is Validated When Supermajority of Peers Calculate the Same Result Result") }} + +_Figure 8: Ledger is Validated When Supermajority of Peers Calculate the Same Result — Each server compares its calculated ledger with the hashes received from its chosen validators. If not in agreement, the server must recalculate or retrieve the correct ledger._ + +Servers in the network recognize a ledger instance as validated when a supermajority of the peers have signed and broadcast the same validation hash 7. Going forward, transactions are applied to this updated and now validated ledger with ledger index N+1. + +In cases where a server is in the minority, having computed a ledger that differs from its peers, the server disregards the ledger it computed 8. It recomputes the correct ledger, or retrieves the correct ledger as needed. + +If the network fails to achieve supermajority agreement on validations, this implies that transaction volume was too high or network latency too great for the consensus process to produce consistent proposals. In this case, the servers repeat the consensus process for a new ledger version. As time passes since consensus began, it becomes increasingly likely that a majority of the servers have received the same set of candidate transactions, as each consensus round reduces disagreement. The XRP Ledger dynamically adjusts [transaction costs](transaction-cost.html) and the time to wait for consensus in response to these conditions. + +Once they reach supermajority agreement on validations, the servers work with the new validated ledger, ledger index N+1. The consensus and validation process repeats 9, considering candidate transactions that were not included in the last round along with new transactions submitted in the meantime. + + +## Key Takeaways + +Transactions submitted to the XRP Ledger are not processed instantaneously. For a period of time, each transaction remains a candidate. + +The lifecycle of a single transaction is as follows: + +- A transaction is created and signed by an account owner. +- The transaction is submitted to the network. + - Badly formed transactions may be rejected immediately. + - Well formed transactions may provisionally succeed, then later fail. + - Well formed transactions may provisionally fail, then later succeed. +- During consensus, the transaction is included in the ledger. + - The result of a successful consensus round is a validated ledger. + - If a consensus round fails, the consensus process repeats until it succeeds. +- The validated ledger includes the transaction and its effects on the ledger state. + +Applications should only rely on information in validated ledgers, not on the provisional results of candidate transactions. Some [`rippled` APIs](http-websocket-apis.html) initially return provisional results for transactions. The results of a transaction become immutable only when that transaction is included in a validated ledger, or the transaction includes `LastLedgerSequence` and does not appear in any validated ledger with that ledger index or lower. + +Best practices for applications submitting transactions include: + +- Use the `LastLedgerSequence` parameter to ensure that transactions validate or fail in a deterministic and prompt fashion. +- Check the results of transactions in validated ledgers. + - Until a ledger containing the transaction is validated, or `LastLedgerSequence` has passed, results are provisional. + - Transactions with result code **`tesSUCCESS`** and `"validated": true` have immutably succeeded. + - Transactions with other result codes and `"validated": true` have immutably failed. + - Transactions that fail to appear in any validated ledger up to and including the validated ledger identified by the transaction’s `LastLedgerSequence` have immutably failed. + - Take care to use a server with a continuous ledger history to detect this case 10. + - It may be necessary to check the status of a transaction repeatedly until the ledger identified by `LastLedgerSequence` is validated. + +## See Also + +- **Concepts:** + - [Introduction to Consensus](intro-to-consensus.html) + - [Consensus Research](consensus-research.html) + - [The Consensus Mechanism (YouTube)](https://www.youtube.com/watch?v=k6VqEkqRTmk&list=PLJQ55Tj1hIVZtJ_JdTvSum2qMTsedWkNi&index=2) +- **Tutorials:** + - [Reliable Transaction Submission](reliable-transaction-submission.html) + - [Run `rippled` as a Validator](run-rippled-as-a-validator.html) +- **References:** + - [Ledger Format Reference](ledger-data-formats.html) + - [Transaction Format Reference](transaction-formats.html) + - [consensus_info method][] + - [validator_list_sites method][] + - [validators method][] + + + + + +## Footnotes + +1 – Transactions with [**tec** result codes](tec-codes.html) do not perform the requested action, but do have effects on the ledger. To prevent abuse of the network and to pay for the cost of distributing the transaction, they destroy the XRP [transaction cost](transaction-cost.html). To not block other transactions submitted by the same sender around the same time, they increment the sending account's [sequence number](basic-data-types.html#account-sequence). Transactions with `tec`-class results sometimes also perform maintenance such as deleting expired objects or unfunded trade offers. + +2 – For example, consider a scenario where Alice has $100, and sends all of it to Bob. If an application first submits that payment transaction, then immediately after checks Alice’s balance, the API returns $0. This value is based on the provisional result of a candidate transaction. There are circumstances in which the payment fails and Alice’s balance remains $100 (or, due to other transactions, become some other amount). The only way to know with certainty that Alice’s payment to Bob succeeded is to check the status of the transaction until it is both in a validated ledger and has result code **`tesSUCCESS`**. If the transaction is in a validated ledger with any other result code, the payment has failed. + +3 – Strictly speaking, validators are a subset of tracking servers. They provide the same features and additionally send "validation" messages. Tracking servers may be further categorized by whether they keep full vs. partial ledger history. + +4 – Transactions fail to pass a round of consensus when the percentage of peers recognizing the transaction falls below a threshold. Each round is an iterative process. At the start of the first round, at least 50% of peers must agree. The final threshold for a consensus round is 80% agreement. These specific values are subject to change + +5 – Each server defines its own trusted validators, but the consistency of the network depends on different servers choosing lists that have a high degree of overlap. For this reason, Ripple publishes a list of recommended validators. + +6 – If proposals from all validators were evaluated, instead of exclusively from the validators chosen not to collude, a malicious attacker could run more validators to gain disproportionate power over the validation process, so they could introduce invalid transactions or omit valid transactions from proposals. The chosen validator list [defends against Sybil attacks](consensus-protections.html#sybil-attacks). + +7 – The supermajority threshold, as of November 2014, requires that at least 80% of peers must agree for a ledger to be validated. This happens to be the same percentage required by a round of consensus. Both thresholds are subject to change and need not be equal. + +8 – In practice, the server detects that it is in the minority before receiving validations from all peers. It knows when it receives non-matching validations from over 20% of peers that its validation cannot meet the 80% threshold. At that point, it can begin to recalculate a ledger. + +9 – In practice, the XRP Ledger runs more efficiently by starting a new round of consensus concurrently, before validation has completed. + +10 – A `rippled` server can respond to API requests even without a complete ledger history. Interruptions in service or network connectivity can lead to missing ledgers, or gaps, in the server’s ledger history. Over time, if configured to, `rippled` fills in gaps in its history. When testing for missing transactions, it is important to verify against a server with continuous complete ledgers from the time the transaction was submitted until its `LastLedgerSequence`. Use the [server_info method][] to determine which ledgers are available to a particular server. + + + +{% include '_snippets/rippled-api-links.md' %} +{% include '_snippets/tx-type-links.md' %} +{% include '_snippets/rippled_versions.md' %} diff --git a/content/concepts/xrpl/consensus.md b/content/concepts/xrpl/consensus.md new file mode 100644 index 0000000000..6284949713 --- /dev/null +++ b/content/concepts/xrpl/consensus.md @@ -0,0 +1,60 @@ +--- +html: consensus.html +parent: validation.html +blurb: Consensus is the validation process for new entries to the XRP Ledger. +labels: + - Ledgers +--- + +# Consensus + +This topic describes the consensus process used to validate each ledger version as it is added to the XRP Ledger block chain. + +Consensus is the most important property of any decentralized payment system. In traditional centralized payment systems, one authoritative administrator gets the final say in how and when payments occur. Decentralized systems, by definition, do not have an administrator to do that. Instead, decentralized systems like the XRP Ledger define a set of rules all participants follow. Every participant can agree on the exact same series of events and their outcome at any point in time. This set of rules is known as a _consensus protocol_. + +## Consensus Process + +The consensus process gathers proposed transactions on the XRP Ledger and generates a new ledger version with agreed upon changes. + +The peer-to-peer XRP Ledger network includes a specialized type of server called a _validator_. Validators collaborate to propose and confirm transactions that generate a new ledger version. + +Starting with the last validated ledger version, validators distribute a new ledger version based on transaction requests they have received. The proposed ledgers all have the same sequence number (previous sequence number plus one). + +[![Proposed Ledgers](img/consensus1-proposed-ledgers.png)](img/consensus1-proposed-ledgers.png) + +Validators then incorporate new transactions from other trusted validators, and remove transactions that are not recognized by other nodes. When 80% of the validator nodes agree on the transactions to include in the new ledger, all proposed ledger versions are dropped and a new one is created with the agreed upon transactions. + +[![Proposed Ledgers](img/consensus2-agreed-transactions.png)](img/consensus2-agreed-transactions.png) + +The XRP Ledger creates the new ledger version, including changes in state information based on the agreed upon transactions, the parent hash, the current available XRP, flags, and the close time. The ledger calculates the unique hash of the ledger version based on its own updated information. + +[![Proposed Ledgers](img/consensus3-updates.png)](img/consensus3-updates.png) + +The XRP Ledger's technology enables near real-time settlement (three to six seconds). + +## Consensus Protocol Properties + +The XRP Ledger Consensus Protocol, is designed with these important properties: + +- Everyone who uses the XRP Ledger can agree on the current state, and which transactions occurred in which order. +- All valid transactions are processed without needing a central operator or having a single point of failure. +- The ledger can make progress, even if some participants join, leave, or behave inappropriately. +- If too many participants are unreachable or misbehaving, the network fails to make progress, rather than diverging or confirming invalid transactions. +- Confirming transactions does not require wasteful or competitive use of resources, unlike most other blockchain systems. + +These properties are sometimes summarized as the following principles, in order of priority: **Correctness, Agreement, Forward Progress**. + +## Consensus Rules + +The primary role of consensus is for participants in the process to agree on which transactions are to be processed as a group to resolve the double spend problem (where an account attempts to use the same funds for two separate transactions). There are four reasons this agreement is easier to achieve than might be expected: + +1. If there is no reason a transaction should not be included in such a group of transactions, all honest participants agree to include it. If all participants already agree, consensus has no work to do. +2. If there is any reason at all a transaction should not be included in such a group of transactions, all honest participants are willing to exclude it. If the transaction is still valid, there is no reason not to include it in the next round, and they should all agree to include it then. +3. It is extremely rare for a participant to particularly care how the transactions were grouped. Agreement is easiest when everyone’s priority is reaching agreement and only challenging when there are diverging interests. +4. Deterministic rules can be used even to form the groupings, leading to disagreement only in edge cases. For example, if there are two conflicting transactions in a round, deterministic rules can be used to determine which is included in the next round. + +Every participant’s top priority is correctness. They must first enforce the rules to be sure nothing violates the integrity of the shared ledger. For example, a transaction that is not properly signed must never be processed (even if other participants want it to be processed). However, every honest participant’s second priority is agreement. A network with possible double spends has no utility at all, so every honest participant values agreement above everything but correctness. + +For more in-depth information on how consensus works, see [Consensus Structure](consensus-structure.html) + +This protocol is still evolving, as is our knowledge of its limits and possible failure cases. For academic research on the protocol itself, see [Consensus Research](consensus-research.html). diff --git a/content/concepts/xrpl/double-spend.md b/content/concepts/xrpl/double-spend.md new file mode 100644 index 0000000000..1150acb361 --- /dev/null +++ b/content/concepts/xrpl/double-spend.md @@ -0,0 +1,34 @@ +--- +html: double-spend.html +parent: consensus.html +blurb: Consensus protocols are a solution to the double-spend problem. +labels: + - Ledgers +--- +# The Double-spend Problem + +Consensus protocols are a solution to the _double-spend problem_: the challenge of preventing someone from successfully spending the same digital money twice. The hardest part about this problem is putting transactions in order: without a central authority, it can be difficult to resolve disputes about which transaction comes first when you have two or more mutually exclusive transactions sent around the same time. + +The double-spend problem is a fundamental challenge to operating any sort of payment system. The problem comes from the requirement that when money is spent in one place, it can't also be spent in another place. More generally, the problem occurs when you have any two transactions such that either one is valid but not both together. + +Suppose Alice, Bob, and Charlie are using a payment system, and Alice has a balance of $10. For the payment system to be useful, Alice must be able to send her $10 to Bob, or to Charlie. However, if Alice tries to send $10 to Bob and also send $10 to Charlie at the same time, that's where the double spend problem comes in. + +If Alice can send the "same" $10 to both Charlie and Bob, the payment system ceases to be useful. The payment system needs a way to choose which transaction should succeed and which should fail, in such a way that all participants agree on which transaction has happened. Either of those two transactions is equally valid on its own. However, different participants in the payment system may have a different view of which transaction came first. + +Conventionally, payment systems solve the double spend problem by having a central authority track and approve transactions. For example, a bank decides to clear a check based on the issuer's available balance, of which the bank is the sole custodian. In such a system, all participants follow the central authority's decisions. + +Distributed ledger technologies, like the XRP Ledger, have no central authority. They must solve the double spend problem using a consensus protocol. + +## Simplifying the Problem + +Much of the double spend problem can be solved by well known rules such as prohibiting an account from spending funds it does not have. In fact, the double spend problem can be reduced to putting transactions in order. + +Consider the example of Alice trying to send the same $10 to both Bob and Charlie. If the payment to Bob is known to be first, then everyone can agree that she has the funds to pay Bob. If the payment to Charlie is known to be second, then everyone can agree that she cannot send those funds to Charlie because the money has already been sent to Bob. + +We can also order transactions by deterministic rules. Because transactions are collections of digital information, it's trivial for a computer to sort them. + +This would be enough to solve the double spend problem without a central authority, but it would require us to have every transaction that would ever occur (so that we could sort them) before we could be certain of the results of any transaction. Of course, that would be impractical. + +If we could collect transactions into groups and agree on those groupings, we could sort the transactions within that group. As long as every participant agrees on which transactions are to be processed as a unit, they can use deterministic rules to solve the double spend problem without any need for a central authority. The participants each sort the transactions and apply them in a deterministic way following the known rules. The XRP Ledger solves the double-spend problem in exactly this way. + +The XRP Ledger allows multiple conflicting transactions to be in the agreed group. The group of transactions is executed according to deterministic rules, so whichever transaction comes first according to the sorting rules succeeds and whichever conflicting transaction comes second fails. \ No newline at end of file diff --git a/content/concepts/xrpl/fee-voting.md b/content/concepts/xrpl/fee-voting.md new file mode 100644 index 0000000000..11ebcb1734 --- /dev/null +++ b/content/concepts/xrpl/fee-voting.md @@ -0,0 +1,55 @@ +--- +html: fee-voting.html +parent: consensus.html +blurb: Validators can vote for changes in the cost of transactions and reserve requirements. +labels: + - Ledgers +--- +# Fee Voting + +Validators can vote for changes to basic transaction cost as well as reserve requirements. If the preferences in a validator's configuration are different than the network's current settings, the validator expresses its preferences to the network periodically. If a quorum of validators agrees on a change, they can apply a change that takes effect thereafter. Validators may do this for various reasons, especially to adjust to long-term changes in the value of XRP. + +Operators of `rippled` validators can set their preferences for the transaction cost and reserve requirements in the `[voting]` stanza of the `rippled.cfg` file. + +**Caution:** Insufficient requirements, if adopted by a consensus of trusted validators, could expose the XRP Ledger peer-to-peer network to denial-of-service attacks. + +The parameters you can set are as follows: + +| Parameter | Description | Recommended Value | +|-----------|-------------|-------------------| +| `reference_fee` | Amount of XRP, in _drops_ (1 XRP = 1 million drops.), that must be destroyed to send the reference transaction, the cheapest possible transaction. The actual transaction cost is a multiple of this value, scaled dynamically based on the load of individual servers. | `10` (0.00001 XRP) | +| `account_reserve` | Minimum amount of XRP, in _drops_, that an account must have on reserve. This is the smallest amount that can be sent to fund a new account in the ledger. | `10000000` (10 XRP) | +| `owner_reserve` | How much more XRP, in _drops_, that an address must hold for _each_ object it owns in the ledger. | `2000000` (2 XRP) | + +## Voting Process + +Every 256th ledger is called a "flag" ledger. (A flag ledger is defined such that the `ledger_index` [modulo](https://en.wikipedia.org/wiki/Modulo_operation) `256` is equal to `0`.) In the ledger immediately before the flag ledger, each validator whose account reserve or transaction cost preferences are different than the current network setting distributes a "vote" message alongside its ledger validation, indicating the values that validator prefers. + +In the flag ledger itself, nothing happens, but validators receive and take note of the votes from other validators they trust. + +After counting the votes of other validators, each validator attempts to compromise between its own preferences and the preferences of a majority of validators it trusts. (For example, if one validator wants to raise the minimum transaction cost from 10 to 100, but most validators only want to raise it from 10 to 20, the one validator settles on the change to raise the cost to 20. However, the one validator never settles on a value lower than 10 or higher than 100.) If a compromise is possible, the validator inserts a [SetFee pseudo-transaction](setfee.html) into its proposal for the ledger following the flag ledger. Other validators who want the same change insert the same SetFee pseudo-transaction into their proposals for the same ledger. (Validators whose preferences match the existing network settings do nothing.) If a SetFee pseudo-transaction survives the consensus process to be included in a validated ledger, then the new transaction cost and reserve settings denoted by the SetFee pseudo-transaction take effect starting with the following ledger. + +In short: + +* **Flag ledger -1**: Validators submit votes. +* **Flag ledger**: Validators tally votes and decide what SetFee to include, if any. +* **Flag ledger +1**: Validators insert SetFee pseudo-transaction into their proposed ledgers. +* **Flag ledger +2**: New settings take effect, if a SetFee pseudo-transaction achieved consensus. + +## Maximum Fee Values + +The maximum possible values for the fees are limited by the internal data types stored in the [FeeSettings ledger object](feesettings.html). These values are as follows: + +| Parameter | Maximum Value (drops) | Maximum Value (XRP) +|-----------|-----------------------|----| +| `reference_fee` | 264 | (More XRP than has ever existed.) | +| `account_reserve` | 232 drops | Approximately 4294 XRP | +| `owner_reserve` | 232 drops | Approximately 4294 XRP | + + +## See Also + +- **Concepts:** + - [Amendments](amendments.html) + - [Transaction Cost](transaction-cost.html) + - [Reserves](reserves.html) \ No newline at end of file diff --git a/content/concepts/xrpl/invariant-checking.md b/content/concepts/xrpl/invariant-checking.md new file mode 100644 index 0000000000..ebecc398a0 --- /dev/null +++ b/content/concepts/xrpl/invariant-checking.md @@ -0,0 +1,159 @@ +--- +html: invariant-checking.html +parent: consensus.html +blurb: Understand what Invariant Checking is, why it exists, how it works, and what invariant checks are active. +labels: + - Blockchain + - Security +--- +# Invariant Checking + +Invariant checking is a safety feature of the XRP Ledger. It consists of a set of checks, separate from normal transaction processing, that guarantee that certain _invariants_ hold true across all transactions. + +Like many safety features, we all hope that invariant checking never actually needs to do anything. However, it can be useful to understand the XRP Ledger's invariants because they define hard limits on the XRP Ledger's transaction processing, and to recognize the problem in the unlikely event that a transaction fails because it violated an invariant check. + +Invariants should not trigger, but they ensure the XRP Ledger's integrity from bugs yet to be discovered or even created. + + +## Why it Exists + +- The source code for the XRP Ledger is complicated and vast; there is a high potential for code to execute incorrectly. +- The cost of incorrectly executing a transaction is high and not acceptable by any standards. + +Specifically, incorrect transaction executions could create invalid or corrupt data that later consistently crashes servers in the network by sending them into an "impossible" state which could halt the entire network. + +The processing of incorrect transaction would undermine the value of trust in the XRP Ledger. Invariant checking provides value to the entire XRP Ledger because it adds the feature of reliability. + + + +## How it Works + +The invariant checker is a second layer of code that runs automatically in real-time after each transaction. Before the transaction's results are committed to the ledger, the invariant checker examines those changes for correctness. If the transaction's results would break one of the XRP Ledger's strict rules, the invariant checker rejects the transaction. Transactions that are rejected this way have the result code `tecINVARIANT_FAILED` and are included in the ledger with no effects. + +To include the transaction in the ledger with a `tec`-class code, some minimal processing is necessary. If this minimal processing still breaks an invariant, the transaction fails with the code `tefINVARIANT_FAILED` instead, and is not included in the ledger at all. + + +## Active Invariants + +The XRP Ledger checks all the following invariants on each transaction: + +[[Source]](https://github.com/ripple/rippled/blob/023f5704d07d09e70091f38a0d4e5df213a3144b/src/ripple/app/tx/impl/InvariantCheck.h#L92 "Source") + +- [Transaction Fee Check](#transaction-fee-check) + +[[Source]](https://github.com/ripple/rippled/blob/023f5704d07d09e70091f38a0d4e5df213a3144b/src/ripple/app/tx/impl/InvariantCheck.h#L118 "Source") + +- [XRP Not Created](#xrp-not-created) + +[[Source]](https://github.com/ripple/rippled/blob/023f5704d07d09e70091f38a0d4e5df213a3144b/src/ripple/app/tx/impl/InvariantCheck.h#L146 "Source") + +- [Account Roots Not Deleted](#account-roots-not-deleted) + +[[Source]](https://github.com/ripple/rippled/blob/023f5704d07d09e70091f38a0d4e5df213a3144b/src/ripple/app/tx/impl/InvariantCheck.h#L173 "Source") + +- [XRP Balance Checks](#xrp-balance-checks) + +[[Source]](https://github.com/ripple/rippled/blob/023f5704d07d09e70091f38a0d4e5df213a3144b/src/ripple/app/tx/impl/InvariantCheck.h#L197 "Source") + +- [Ledger Entry Types Match](#ledger-entry-types-match) + +[[Source]](https://github.com/ripple/rippled/blob/023f5704d07d09e70091f38a0d4e5df213a3144b/src/ripple/app/tx/impl/InvariantCheck.h#L224 "Source") + +- [No XRP Trust Lines](#no-xrp-trust-lines) + +[[Source]](https://github.com/ripple/rippled/blob/023f5704d07d09e70091f38a0d4e5df213a3144b/src/ripple/app/tx/impl/InvariantCheck.h#L251 "Source") + +- [No Bad Offers](#no-bad-offers) + +[[Source]](https://github.com/ripple/rippled/blob/023f5704d07d09e70091f38a0d4e5df213a3144b/src/ripple/app/tx/impl/InvariantCheck.h#L275 "Source") + +- [No Zero Escrow](#no-zero-escrow) + +[[Source]](https://github.com/ripple/rippled/blob/023f5704d07d09e70091f38a0d4e5df213a3144b/src/ripple/app/tx/impl/InvariantCheck.h#L300 "Source") + +- [Valid New Account Root](#valid-new-account-root) + + +### Transaction Fee Check + +- **Invariant Condition(s):** + - The [transaction cost](transaction-cost.html) amount must never be negative, nor larger than the cost specified in the transaction. + + +### XRP Not Created + +- **Invariant Condition(s):** + - A transaction must not create XRP and should only destroy the XRP [transaction cost](transaction-cost.html). + + +### Account Roots Not Deleted + +- **Invariant Condition(s):** + - An [account](accounts.html) cannot be deleted from the ledger except by an [AccountDelete transaction][]. + - A successful AccountDelete transaction always deletes exactly 1 account. + + +### XRP Balance Checks + +- **Invariant Condition(s):** + - An account's XRP balance must be of type XRP, and it cannot be less than 0 or more than 100 billion XRP exactly. + + +### Ledger Entry Types Match + +- **Invariant Condition(s):** + - Corresponding modified ledger entries should match in type and added entries should be a [valid type](ledger-object-types.html). + + +### No XRP Trust Lines + +- **Invariant Condition(s):** + - [Trust lines](trust-lines-and-issuing.html) using XRP are not allowed. + + +### No Bad Offers + +- **Invariant Condition(s):** + - [Offers](offer.html) should be for non-negative amounts and must not be XRP to XRP. + + +### No Zero Escrow + +- **Invariant Condition(s):** + - An [escrow](escrow-object.html) entry must hold more than 0 XRP and less than 100 billion XRP. + + +### Valid New Account Root + +- **Invariant Condition(s):** + - A new [account root](accountroot.html) must be the consequence of a payment. + - A new account root must have the right starting [sequence](basic-data-types.html#account-sequence). + - A transaction must not create more than one new [account](accounts.html). + + + + + + +{% include '_snippets/rippled-api-links.md' %} +{% include '_snippets/tx-type-links.md' %} +{% include '_snippets/rippled_versions.md' %} diff --git a/content/concepts/xrpl/ledger-close-times.md b/content/concepts/xrpl/ledger-close-times.md new file mode 100644 index 0000000000..21286e75e2 --- /dev/null +++ b/content/concepts/xrpl/ledger-close-times.md @@ -0,0 +1,43 @@ +--- +html: ledger-close-times.html +parent: open-closed-validated-ledgers.html +blurb: How the XRP Ledger calculates a unique close time value for each ledger version. +labels: + - Ledgers +--- + +# Ledger Close Times + + + +The time that a ledger version closes is recorded in the `close_time` field of the ledger header. To make it easier for the network to reach a consensus on an exact close time, this value is rounded to a number of seconds based on the close time resolution, currently 10 seconds. If rounding would cause a ledger's close time to be the same as (or earlier than) its parent ledger's, the child ledger has its close time set to the parent's close time plus 1. This guarantees that the close times of validated ledgers are strictly increasing. + +Since new ledger versions usually close about every 3 to 5 seconds, these rules result in a loose pattern where ledger close times end in :00, :01, :02, :10, :11, :20, :21, and so on. Times ending in 2 are less common and times ending in 3 are very rare, but both occur when more ledgers randomly happen to close within a 10-second window. + +Generally speaking, the ledger cannot make any time-based measurements that are more precise than the close time resolution. For example, to check if an object has passed an expiration date, the rule is to compare it to the close time of the parent ledger. (The close time of a ledger is not yet known when executing transactions to go into that ledger.) This means that, for example, an Escrow could successfully finish at a real-world time that is up to 10 seconds later than the time-based expiration specified in the Escrow object. + +### Example + +The following examples demonstrate the rounding behavior of ledger close times, from the perspective of an example validator, following a ledger with the close time **12:00:00**: + +**Current consensus round** + +1. A validator notes that it was **12:00:03** when the ledger closed and entered consensus. The validator includes this close time in its proposals. +2. The validator observes that most other validators (on its UNL) proposed a close time of 12:00:02, and one other proposed a close time of 12:00:03. It changes its proposed close time to match the consensus of **12:00:02**. +3. The validator rounds this value to the nearest close time interval, resulting in **12:00:00**. +4. Since 12:00:00 is not greater than the previous ledger's close time, the validator adjusts the close time to be exactly 1 second after the previous ledger's close time. The result is an adjusted close time of **12:00:01**. +5. The validator builds the ledger with these details, calculates the resulting hash, and confirms in the validation step that others did the same. + +Non-validating servers do all the same steps, except they do not propose their recorded close times to the rest of the network. + +**Next consensus round** + +1. The next ledger enters consensus at **12:00:04** according to most validators. +2. This rounds down again, to a close time of **12:00:00**. +3. Since this is not greater than the previous ledger's close time of 12:00:01, the adjusted close time is **12:00:02**. + +**Next consensus round after that** + +1. The ledger after that enters consensus at **12:00:05** according to most validators. +2. This rounds up, based on the close time resolution, to **12:00:10**. +3. Since this value is larger than the previous ledger's close time, it does not need to be adjusted. **12:00:10** becomes the official close time. diff --git a/content/concepts/xrpl/ledger-structure.md b/content/concepts/xrpl/ledger-structure.md new file mode 100644 index 0000000000..a4f10578f6 --- /dev/null +++ b/content/concepts/xrpl/ledger-structure.md @@ -0,0 +1,71 @@ +--- +html: ledger-structure.html +parent: ledgers.html +blurb: A closer look at the elements to be found in each XRP Ledger entry. +labels: + - Ledgers +--- + +# XRP Ledger Structure + +The XRP Ledger is a block chain system, linking immutable data blocks in a meaningful sequence. This topic examines the data blocks that make up the XRPL block chain. + +The XRP Ledger processes transactions in blocks called _ledger versions_. Each ledger version contains state data, a transaction set, and metadata. + +The main job of the XRP Ledger Consensus Protocol is to agree on a set of transactions to apply to the previous ledger, apply them in a well defined order, then confirm that all validators get the same results. When this happens successfully, a ledger version is considered _validated_, and final. From there, the process continues by building the next ledger version. + +[![Ledger Version](img/ledger.png)](img/ledger.png) + +Each data block in the XRPL chain is a _ledger version_. A ledger version is comprised of the following elements. + +The _ledger index_ identifies the ledger version position in the chain at the time of its validation. It builds on the version with an index that is one lower, back to the starting point known as the _genesis ledger_. This forms a public history of all transactions and results. + +[![Sequence Number](img/ledger1-sequence-number.png)](img/ledger1-sequence-number.png) + +Each ledger version also identifies itself with a unique 64-character hexidecimal _hash number_. + +[![Hash Number](img/ledger2-unique-hash.png)](img/ledger2-unique-hash.png) + +Ledger versions are largely defined as the difference between the current version and its _parent version_, identified by its unique hash number. + +[![Parent Version](img/ledger3-parent-version.png)](img/ledger3-parent-version.png) + +Every change made from version to version is the result of a validated transaction. The ledger version stores information about transactions in its scope. + +[![Transactions](img/ledger4-transactions.png)](img/ledger4-transactions.png) + +The ledger version contains _state data_ for all accounts, along with some miscellaneous housekeeping information. 99% or more of the data tends to be the same from version to version. While every rippled server keeps a copy of the entire ledger history, each ledger version saves only the updates to the state data. + +[![State Data](img/ledger5-state-data.png)](img/ledger5-state-data.png) + +Every transaction has a minor cost that removes a small amount of XRP from the available pool. The ledger version keeps track of the full amount of _available XRP_ still in circulation, in drops. The number of actual XRP in circulation is smaller than the amount in the ledger due to some XRP having been sent to "black hole" accounts where the access information is unknown, either by default or design. + +[![Available XRP](img/ledger6-available-xrp.png)](img/ledger6-available-zrp.png) + +_Close Flags_ is a bit map of flags related to the close of the ledger. Currently, the only flag defined is **sLCF_NoConsensusTime** (value 1). It means that validators disagreed on the close time, but otherwise built the same ledger, so they have decided to "agree to disagree" on the close time. Other flags might be defined in future amendments to the XRP Ledger. + +[![Close Flags](img/ledger7-close-flags.png)](img/ledger7-close-flags.png) + +_Close Time_ is the official timestamp when the final validated ledger version is created and closed. + +[![Close Time](img/ledger8-close-time.png)](img/ledger8-close-time.png) + +80% or more of the validators in the server's Unique Node List must agree on the contents of the ledger. Once it is validated, it is immutable. The ledger can only be changed by subsequent transactions. + +[![Validated Ledger](img/ledger.png)](img/ledger.png) + + +## Tree Format + + + +As its name might suggest, a ledger's state tree is a tree data structure. Each object in the state tree is identified by a 256-bit object ID. In JSON, a ledger object's ID is the `index` field, which contains a 64-character hexadecimal string like `"193C591BF62482468422313F9D3274B5927CA80B4DD3707E42015DD609E39C94"`. Every object in the state tree has an ID that you can use to look up that object; every transaction has an identifying hash that you can use to look up the transaction in the transaction tree. Do not confuse the `index` (ID) of a ledger object with the `ledger_index` (sequence number) of a ledger. + +**Tip:** Sometimes, an object in the ledger's state tree is called a _ledger node_. For example, transaction metadata returns a list of `AffectedNodes`. Do not confuse this with a _node_ (server) in the peer-to-peer network. + +In the case of transactions, the identifying hash is based on the signed transaction instructions. When you look up the transaction, its contents contain the results and metadata of the transaction, which are not taken into account when generating the hash. + + + + + diff --git a/content/concepts/xrpl/ledgers.md b/content/concepts/xrpl/ledgers.md new file mode 100644 index 0000000000..8c019566fb --- /dev/null +++ b/content/concepts/xrpl/ledgers.md @@ -0,0 +1,26 @@ +--- +html: ledgers.html +parent: concepts.html +blurb: The XRP Ledger is a blockchain that records transactions of XRP and other tokens between accounts. +labels: + - Ledgers +--- + +# Ledgers + +The XRP Ledger is a global distributed blockchain that is open to all. Individual participants can trust the integrity of the ledger without having to trust any single institution to manage it. The `rippled` server software accomplishes this by managing a ledger database that can only be updated according to very specific rules. + +Each instance of `rippled` keeps a full copy of the ledger. The peer-to-peer network of `rippled` servers distributes candidate transactions to all other `rippled` servers. The consensus process determines which transactions are applied to each new version of the ledger. + +The shared global ledger is a series of individual ledger versions that `rippled` keeps in its internal database. Every ledger version has a Ledger Index value that identifies the order of ledger versions. Each permanent, closed ledger version has a unique, identifying hash value. + +At any given time, a `rippled` instance has an in-progress _open_ ledger, a number of _closed_ ledgers that have not yet been approved, and any number of ledgers that have been _validated_ by consensus. Only the validated ledgers are certain to be correct and immutable. The following table summarizes the difference: + +A single ledger version consists of three parts: + +* A **header** - The Ledger Index, hashes of its other contents, and other metadata. +* A **transaction tree** - The transactions that were applied to the previous ledger version to create this version. Transactions are the _only_ way to change the ledger. +* A **state tree** - All the ledger objects that contain the settings, balances, and objects in the ledger as of this version. + +See [Ledger Structure](ledger-structure.html) for a complete description of the elements of an XRP Ledger object. + diff --git a/content/concepts/xrpl/negative-unl.md b/content/concepts/xrpl/negative-unl.md new file mode 100644 index 0000000000..e182066a35 --- /dev/null +++ b/content/concepts/xrpl/negative-unl.md @@ -0,0 +1,182 @@ +--- +html: negative-unl.html +parent: consensus.html +blurb: Negative UNL improves the network's ability to make progress during a partial outage. +labels: + - Ledgers +--- + +# Negative UNL + +_Added by the [NegativeUNL Amendment](known-amendments.html#negativeunl)._ + +The _Negative UNL_ is a feature of the XRP Ledger [consensus protocol](consensus.html) that improves _liveness_, the network's ability to make forward progress during a partial outage. Using the Negative UNL, servers adjust their effective UNLs based on which validators are currently online and operational, so that a new [ledger version](ledgers.html) can be declared _validated_ even if several trusted validators are offline. + +The Negative UNL has no impact on how the network processes transactions or what transactions' outcomes are, except that it improves the network's ability to declare outcomes final during some types of partial outages. + +## Background + +Each server in the XRP Ledger protocol has its own UNL (Unique Node List), a list of validators it trusts not to collude, and each server independently decides when a ledger version is validated based on the consensus when enough of its trusted validators agree on a new ledger version. (The default configuration uses a recommended UNL, signed by Ripple, consisting of validators Ripple considers to be sufficiently unique, reliable, and independent.) The standard quorum requirement is at least 80% of trusted validators must agree. + +If more than 20% of trusted validators go offline or become unable to communicate with the rest of the network, the network stops validating new ledgers because it cannot reach a quorum. This is a design choice to ensure that no transactions' outcomes can be changed after they are declared final. During such a situation, the remaining servers would still be online and could provide past and tentative transaction data, but could not confirm the final, immutable outcome of new transactions. + +However, this means that the network could stop making forward progress if a few widely-trusted validators went offline. As of 2020-10-06, there are 34 validators in Ripple's recommended UNL, so the network would stop making forward progress if 7 or more of them were offline. Furthermore, if one or two validators are out for an extended period of time, the network has less room for disagreement between the remaining validators, which can make it take longer to achieve a consensus. + +## Summary + +It is not reasonable to expect a diverse set of validators to maintain 100% uptime: many things can cause a validator to become temporarily unavailable, such as: hardware maintenance, software upgrades, internet connectivity problems, targeted attacks, human error, hardware failures, and outside circumstances like natural disasters. + +The "Negative UNL" is **a list of trusted validators which are believed to be offline or malfunctioning**, as declared by a consensus of the remaining validators. Validators in the Negative UNL are ignored for determining if a new ledger version has attained a consensus. + +When a validator that is on the Negative UNL comes back online and sends consistent validation votes, the remaining validators remove it from the Negative UNL after a short time. + +In cases where validators go offline one or two at a time, the remaining validators can use the Negative UNL to gradually adjust their effective UNLs, so that the network only ever needs 80% of the _online_ validators to achieve a quorum. To prevent the network from fragmenting, the quorum has a hard minimum of 60% of _total_ validators. + +If more than 20% of validators suddenly go offline all at once, the remaining servers cannot achieve the quorum necessary to validate a new ledger, so no new ledgers could be validated. However, those servers can still make tentative forward progress through successive consensus rounds. Over time, the remaining validators would continue to apply changes to the Negative UNL to the tentative ledgers and adjust their effective UNLs; eventually, if the situation persists, the network could resume fully validating ledgers by using the adjusted Negative UNL from the tentative ledger versions. + +Negative UNL has no effect on [stand-alone mode](rippled-server-modes.html) since the server does not use consensus in stand-alone mode. + + +## Enabling the Negative UNL for Testing + +Negative UNL functionality is currently available for testing on [Devnet](parallel-networks.html). You can test the Negative UNL feature by adding or modifying a `[features]` stanza in your `rippled.cfg` file, as described in [Connect Your rippled to a Parallel Network](connect-your-rippled-to-the-xrp-test-net.html). + + + +## How It Works + +The Negative UNL is closely tied to the [consensus process](consensus.html) and is designed with safeguards to maintain the continuity and reliability of the network in adverse situations. When all trusted validators are operating normally, the Negative UNL is unused and has no effect. When some validators appear to be offline or out of sync, the Negative UNL rules take effect. + +The Negative UNL is intentionally designed to change at a slow rate, to avoid any time-based disagreements about which Negative UNL should apply to a given ledger version's consensus process. + + +### Reliability Measurement + +Each server in the network has a UNL, the list of validators it trusts not to collude. (By default, a server's exact UNL is configured implicitly based on the recommended validator list Ripple publishes.) Each server tracks the _reliability_ of its trusted validators using a single metric: the percentage of the last 256 ledgers where the validator's validation vote matched the server's view of consensus. In other words: + +> Reliability = Va ÷ 256 + +Va is the total number of validation votes received from one validator for the last 256 ledgers that matched the server's own view of consensus. + +This metric of reliability measures the availability of a validator _and_ the behavior of that validator. A validator should have a high reliability score if it is in sync with the rest of the network and following the same protocol rules as the server scoring it. A validator's reliability score can suffer for any of the following reasons: + +- The validator's validation votes are not reaching the server due to poor network connectivity between them. +- The validator stops operating or gets overloaded. +- The validator is not following the same protocol rules as the server, for a variety of reasons. Possibilities include misconfiguration, software bugs, intentionally following a [different network](parallel-networks.html), or malicious behavior. + +If a validator's reliability is **less than 50%**, it is a candidate to be added to the Negative UNL. To be removed from the Negative UNL, a validator's reliability must be **greater than 80%**. + +Each server, including validators, independently calculates reliability scores for all of its trusted validators. Different servers may reach different conclusions about a validator's reliability, either because that validator's votes reached one server and not the other, or because they happened to disagree about specific ledgers more or less often. To add or remove a validator from the Negative UNL, a consensus of trusted validators must agree that a particular validator is above or below the reliability threshold. + +**Tip:** Validators track their own reliability, but do not propose adding themselves to the Negative UNL. A validator's measure of its own reliability cannot take into account how successfully its validation votes propagate through the network, so it is less dependable than measurements from outside servers. + + + +### Modifying the Negative UNL + +A ledger version is considered a _flag ledger_ if its ledger index is evenly divisible by 256. The Negative UNL can be modified only on flag ledgers. (Flag ledgers occur about once every 15 minutes on the XRP Ledger Mainnet. They may be farther apart in test networks that have low transaction volume.) + +Each flag ledger, all of the following changes apply: + +1. Changes to the Negative UNL that were scheduled in the previous flag ledger go into effect for the following ledger version. The consensus process for validating this flag ledger itself does not use the scheduled change. + + **Note:** This is one of the only times a ledger's state data is modified without a [transaction](transaction-basics.html) or [pseudo-transaction](pseudo-transaction-types.html). + +2. If the Negative UNL is not full, each server proposes adding **up to 1** validator to the Negative UNL from among its trusted validators with less than 50% reliability. +3. If the Negative UNL is not empty, each server proposes removing **up to 1** validator from the Negative UNL. A server can propose removing a validator from the Negative UNL for two reasons: + - It scores that validator with > 80% reliability. + - It does not have that validator in its UNL. (If a validator goes down permanently, this rule ensures that it gets removed from the on-ledger Negative UNL after it has been removed from servers' configured UNLs.) +4. If a proposed change to the Negative UNL achieves a consensus, the change is scheduled to go into effect in the following flag ledger. Up to one addition and one removal can be scheduled this way. + +The proposals to add and remove validators from the Negative UNL take the form of [UNLModify pseudo-transactions][]. The consensus process determines whether each pseudo-transaction achieves a consensus or gets thrown out, in the same way as other [pseudo-transactions](pseudo-transaction-types.html). In other words, for a particular validator to be added or removed from the Negative UNL, a consensus of servers must propose the same change. + +Scheduled and effective changes to the Negative UNL are tracked in the [NegativeUNL object](negativeunl.html) in the ledger's state data. + + +### Negative UNL Limits + +To prevent the network from fragmenting into two two or more sub-networks, the Negative UNL cannot reduce the quorum requirement to less than 60% of the _total_ UNL entries. To enforce this, a server considers the Negative UNL to be "full" if the number of validators on the Negative UNL is 25% (rounded down) of the number of validators in the server's configured UNL. (The 25% is based on the calculation that if 25% of validators are removed, an 80% consensus of the remaining 75% equals 60% of the original number.) If a server considers the Negative UNL to be full, it won't propose new additions to the Negative UNL; but, as usual, the final outcome depends on what a consensus of trusted validators do. + + +### Choosing From Multiple Candidate Validators + +It is possible that multiple validators may be candidates to be added to the Negative UNL, based on the reliability threshold. Since at most one validator can be added to the Negative UNL at a time, servers must choose which validator to propose adding. If there are multiple candidates, the server chooses which one to propose with the following mechanism: + +1. Start with the ledger hash of the parent ledger version. +0. Take the public key of each candidate validator. +0. Calculate the exclusive-or value (XOR) of the candidate validator and the parent ledger's hash. +0. Propose the validator the numerically lowest result of the XOR operation. + +If there are multiple candidates to be removed from the Negative UNL in a given flag ledger, servers use the same mechanism to choose among them. + +This mechanism has several useful properties: + +- It uses information that is readily available to all servers and can be calculated quickly. +- Most servers choose the same candidate even if they calculated slightly different scores for their trusted validators. This holds even if those servers disagree on which validator is _least_ or _most_ reliable. This even holds in many cases where the servers disagree on whether some validators are above or below the reliability thresholds. So, the network is likely to achieve a consensus on which validator to add or remove. +- It does not always give the same results each ledger version. If one proposed change to the Negative UNL fails to achieve a consensus, the network does not get stuck with some servers trying and failing to add or remove that one validator every time. The network can attempt to add or remove a different candidate to the Negative UNL in a later flag ledger. + + +### Filtering Validations + +During the validation step of the consensus process, validators in the parent ledger's Negative UNL are disabled. Each server calculates an "effective UNL" consisting of its configured UNL with the disabled validators removed, and recalculates its quorum. (The quorum is always at least 80% of the effective UNL and at least 60% of the configured UNL.) If a disabled validator sends validation votes, servers track those votes for purposes of calculating the disabled validator's reliability measurement, but they do not use those votes towards determining whether a ledger version has achieved a consensus. + +**Note:** The Negative UNL adjusts the _total_ trusted validators that the quorum is calculated from, not the quorum directly. The quorum is a percentage but the number of votes is a whole number, so reducing the total trusted validators does not always change the number of votes required to reach a quorum. For example, if there are 15 total validators, 80% is 12 validators exactly. If you reduce the total to 14 validators, 80% is 11.2 validators, which means that it still requires 12 validators to reach a quorum. + +The Negative UNL has no impact on the other parts of the consensus process, such as choosing which transactions to include in the proposed transaction set. Those steps always rely on the configured UNL, and the thresholds are based on how many trusted validators are actively participating in the consensus round. Even a validator that is in the Negative UNL can participate in the consensus process. + +### Example + +The following example demonstrates how the Negative UNL affects the consensus process: + +1. Suppose your server's UNL consists of 38 trusted validators, so an 80% quorum is at least 31 of 38 trusted validators. + +{{ include_svg("img/negative-unl-01.svg", "Diagram: Normal case: Negative UNL unused, quorum is 80% of configured validators.") }} + +2. Imagine 2 of those validators, named MissingA and UnsteadyB, appear to have gone offline. (Both of them have reliability scores < 50%.) During the consensus process for ledger _N_, many of the remaining validators propose adding UnsteadyB to the negative UNL. The motion passes via a quorum of at least 31 of the remaining validators, and ledger _N_ becomes validated with UnsteadyB scheduled to be disabled. + +{{ include_svg("img/negative-unl-02.svg", "Diagram: UnsteadyB is scheduled to be disabled.") }} + + +3. For ledgers _N+1_ through _N+256_, the consensus process continues without changes. + +4. In the next flag ledger, ledger _N+256_, UnsteadyB gets automatically moved from "scheduled" to the "disabled" list in the ledger. Also, since MissingA is still offline, a consensus of validators schedules MissingA to be disabled in the next flag ledger. + +{{ include_svg("img/negative-unl-04.svg", "Diagram: UnsteadyB gets disabled and MissingA is scheduled to be disabled, too.") }} + +5. For ledgers _N+257_ through _N+512_, the quorum is now 30 of 37 validators. + +6. UnsteadyB comes back online in ledger _N+270_. It sends validation votes that agree with the rest of the network for ledgers _N+270_ through _N+511_, giving it a reliability score of > 80%. + +{{ include_svg("img/negative-unl-06.svg", "Diagram: UnsteadyB comes back online, but it's still disabled.") }} + +7. In the next flag ledger, _N+256_, MissingA gets automatically moved to the disabled list, as scheduled. Meanwhile, a consensus of validators schedule UnsteadyB to be removed from the Negative UNL, due to its improved reliability score. + +{{ include_svg("img/negative-unl-07.svg", "Diagram: MissingA is disabled and UnsteadyB is scheduled to be re-enabled.") }} + +8. For ledgers _N+513_ through _N+768_, the quorum is 29 of 36 validators. UnsteadyB continues to send validations stably while MissingA remains offline. + +9. In flag ledger _N+768_, UnsteadyB gets automatically removed from the disabled list, as scheduled. + +{{ include_svg("img/negative-unl-09.svg", "Diagram: UnsteadyB is removed from the disabled list.") }} + +10. Eventually, you decide that MissingA is probably not coming back, so you remove it from your server's configured UNL. Your server starts proposing removing MissingA from the Negative UNL each flag ledger thereafter. + +{{ include_svg("img/negative-unl-10.svg", "Diagram: After removing MissingA from the configured UNL, it's proposed for removal from the Negative UNL, too.") }} + +11. As validator operators remove MissingA from their configured UNLs, their validators vote to also remove MissingA from the Negative UNL. When enough validators have done so, the proposal to remove MissingA achieves a consensus, and MissingA is scheduled, then finally removed from the Negative UNL. + +{{ include_svg("img/negative-unl-11.svg", "Diagram: MissingA is removed from the Negative UNL.") }} + + +## See Also + +- **Concepts:** + - [Consensus Protocol](consensus.html) +- **Tutorials:** + - [Connect Your `rippled` to a Parallel Network](connect-your-rippled-to-the-xrp-test-net.html) + - [Run `rippled` as a Validator](run-rippled-as-a-validator.html) +- **References:** + - [NegativeUNL Object](negativeunl.html) + - [UNLModify pseudo-transaction][] + - [ledger_entry method][] + - [consensus_info method][] diff --git a/content/concepts/xrpl/open-closed-validated-ledgers.md b/content/concepts/xrpl/open-closed-validated-ledgers.md new file mode 100644 index 0000000000..63d60df308 --- /dev/null +++ b/content/concepts/xrpl/open-closed-validated-ledgers.md @@ -0,0 +1,33 @@ +--- +html: open-closed-validated-ledgers.html +parent: validation.html +blurb: Ledger objects have one of three states — open, closed, or validated. +labels: + - Ledgers +--- + +# Open, Closed, and Validated Ledgers + +The `rippled` server makes a distinction between ledger versions that are open, closed, and validated. A server has one open ledger, any number of closed but unvalidated ledgers, and an immutable history of validated ledgers. + + The following table summarizes the difference: + +| Ledger Type: | Open | Closed | Validated | +|:---------------------------------|:----------------------------|:-------------------------------------------|:--| +| **Purpose:** | Temporary workspace | Proposed next state | Confirmed previous state | +| **Number used:** | 1 | Any number, but usually 0 or 1 | One per ledger index, growing over time | +| **Can contents change?** | Yes | No, but the whole ledger could be replaced | Never | +| **Transactions are applied in:** | The order they are received | Canonical order | Canonical order | + +The XRP Ledger never "closes" an open ledger to convert it into a closed ledger. Instead, the server throws away the open ledger, creates a new closed ledger by applying transactions on top of a previous closed ledger, then creates a new open ledger using the latest closed ledger as a base. + +For an open ledger, servers apply transactions in the order those transactions appear, but different servers might see transactions different orders. Since there is no central timekeeper to decide which transaction was actually first, servers can disagree on the exact order of transactions that were sent around the same time. The process for calculating a closed ledger version that is eligible for [validation](consensus.html#validation) is different than the process of building an open ledger from proposed transactions in the order they arrive. To create a "closed" ledger, each XRP Ledger server starts with a set of transactions and a previous, or "parent", ledger version. The server puts the transactions in a canonical order, then applies them to the previous ledger in that order. The canonical order is designed to be deterministic, efficient, and hard to game. + +An open ledger is only used as a temporary workspace. The temporary results might vary from the validated ledger. + +## See Also + +- For more information on how the XRP Ledger calculates unique close times for each ledger see [Ledger Close Times](ledger-close-times.html) + +- For more information about ledger headers, ledger object IDs, and ledger object types, see [Ledger Data Formats](ledger-data-formats.html) +- For information on how servers track the history of changes to ledger state, see [Ledger History](ledger-history.html) diff --git a/content/concepts/xrpl/validation.md b/content/concepts/xrpl/validation.md new file mode 100644 index 0000000000..262be8bc41 --- /dev/null +++ b/content/concepts/xrpl/validation.md @@ -0,0 +1,21 @@ +--- +html: validation.html +parent: ledgers.html +blurb: The XRP Ledger's consensus mechanism facilitates approval of ledgers by trusted validators. +labels: + - Ledgers +--- + +# Validation + +Each participant in the XRP Ledger network chooses a set of _validators_, servers specifically configured to participate actively in consensus. The validators are run by different parties who are expected to behave honestly. More importantly, you choose that are not likely to collude with one another to break the rules. This list is sometimes called a _Unique Node List_, or UNL. + +As the network progresses, each server listens to its trusted validators. When a large enough percentage of them agree that a set of transactions should occur, the server declares a consensus. If they do not agree, validators modify their proposals to more closely match the other trusted validators, repeating the process in several rounds until they reach consensus. + +[![Validation Rounds](img/consensus-rounds.svg)](img/consensus-rounds.svg) + +It does not matter if a small proportion of validators do not work properly every time. As long as fewer than 20% of trusted validators are faulty, consensus can continue unimpeded; confirming an invalid transaction would require over 80% of trusted validators to collude. If more than 20% but less than 80% of trusted validators are faulty, the network stops making progress. + +For more information on how consensus works, see [Consensus](consensus-concept.html). + +For a longer exploration of how the XRP Ledger Consensus Protocol responds to various challenges, attacks, and failure cases, see [Consensus Protections](consensus-protections.html). \ No newline at end of file diff --git a/content/concepts/xrpl/xrpl-ecosystem.md b/content/concepts/xrpl/xrpl-ecosystem.md new file mode 100644 index 0000000000..0894a83247 --- /dev/null +++ b/content/concepts/xrpl/xrpl-ecosystem.md @@ -0,0 +1,53 @@ +# Understanding the XRPL Ecosystem + +The XRP Ledger is a layered ecosystem of software projects that power and enable the Internet of Value. It is impossible to list every project, tool, and business that interacts with the XRP Ledger. This page highlights some core projects. + +- The base of the ledger is a peer-to-peer network of always-on servers sharing transactions, engaging in the consensus process and coordinating transactions. + +- Programming libraries provide methods to interact with the XRP Ledger. + +- Middleware provides indirect access to XRP Ledger data. + +- Apps and Services provide user-level interaction with the XRP Ledger. + + +## rippled: The Core Server + +The peer-to-peer network at the heart of the XRP Ledger requires a highly reliable, efficient server to enforce the rules of consensus and transaction processing. Ripple manages and publishes a reference implementation of this server software, called `rippled` (pronounced "ripple-dee"). The server is available under a permissive open-source license. Anyone can inspect and modify their own instance of the server, and re-publish with few restrictions. + +[![Peer-to-Peer Network](../../../img/ecosystem1-peer-to-peer.png)](../../../img/ecosystem1-peer-to-peer.png) + +Every XRPL instance of `rippled` syncs to the same network and has access to all communications across the network. Every `rippled` server on the network keeps a complete copy of the latest state data for the entire XRP Ledger. Each server stores a slice of recent transactions and a record of the changes those transactions made. Every server processes every transaction independently, while verifying that its outcome matches the rest of the network. Servers can be configured to keep more ledger history and to participate in the _consensus_ process as a _validator_. + +`rippled` APIs allow users to look up data, administer the server, and submit transactions. + +## Programming Libraries + +Programming libraries are not strictly required to access XRP Ledger data, since you can use HTTP or WebSocket to connect to the `rippled` APIs directly. Libraries simplify some of the common work of accessing the `rippled` APIs, and convert the data into forms that are easier to understand and program in the programming language of the library. + +[![Programming Libraries](../../../img/ecosystem2-programming-libraries.png)](../../../img/ecosystem2-programming-libraries.png) + +## Middleware + +Middleware services are programs that consume XRP Ledger APIs on one side and provide their own APIs on the other side. They provide a layer of abstraction to make it easier to build higher level applications by providing some common functionality as a service. + +[![Middleware](../../../img/ecosystem3-middleware.png)](../../../img/ecosystem3-middleware.png) + +Unlike programming libraries, which start and shut down with the program that imports them, middleware services typically stay running indefinitely. Middleware services can have their own databases and configuration files. + +The Data API is an example of a middleware service on top of the XRP Ledger. The Data API collects and transforms XRP Ledger data so that you can query by time, filter by data type, or perform data analysis. + +XRP-API is another middleware service. XRP-API manages secret keys, and provides a more convenient RESTful interface to the XRP Ledger for apps in any programming language. + +## Apps and Services + +Apps and services provide a way for users and devices to connect to the XRP Ledger. At this level, exchanges list XRP, gateways issue other currencies for use in the decentralized exchange, and wallets provide user interfaces for buying, selling, or holding XRP. Many other possibilities exist, including additional services layered even higher. + +[![Apps & Services](../../../img/ecosystem4-apps.png)](../../../img/ecosystem4-apps.png) + +One way to build applications that are compatible with not only XRP but also other ways of denominating value is to use the Interledger Protocol with settlement in XRP. + +There are many other examples of projects using XRP and adjacent technologies to interact with users. + + \ No newline at end of file