mirror of
https://github.com/XRPLF/xrpl-dev-portal.git
synced 2025-11-28 07:35:50 +00:00
Merge branch 'master' into reorg-consensus-network
This commit is contained in:
85
content/concepts/decentralized-exchange/offers.md
Normal file
85
content/concepts/decentralized-exchange/offers.md
Normal file
@@ -0,0 +1,85 @@
|
||||
# Offers
|
||||
|
||||
In the XRP Ledger's decentralized exchange, orders to trade currency are called "Offers". Offers can trade XRP with issued currencies, or issued currencies with each other, including issued currencies with the same currency code but different issuers. (Currencies with the same code but different issuers can also sometimes be exchanged through [rippling](rippling.html).)
|
||||
|
||||
- To create an Offer, send an [OfferCreate transaction][].
|
||||
- Offers that aren't fully filled immediately become [Offer objects](offer.html) in the ledger data. Later Offers and Payments can consume the Offer object from the ledger.
|
||||
- [Cross-currency payments](cross-currency-payments.html) consume offers to provide liquidity.
|
||||
|
||||
## Lifecycle of an Offer
|
||||
|
||||
When an OfferCreate transaction is processed, it automatically consumes matching or crossing offers to the extent possible. (If existing offers provide a better rate than requested, the offer creator could pay less than the full `TakerGets` amount to receive the entire `TakerPays` amount.) If that does not completely fulfill the `TakerPays` amount, then the offer becomes an Offer object in the ledger. (You can use [OfferCreate Flags](offercreate.html#offercreate-flags) to modify this behavior.)
|
||||
|
||||
An offer in the ledger can be fulfilled either by additional OfferCreate transactions that match up with the existing offers, or by [Payment transactions][] that use the offer to connect the payment path. Offers can be partially fulfilled and partially funded. A single transaction can consume up to 850 Offers from the ledger. (Any more than that, and the metadata becomes too large, resulting in [`tecOVERSIZE`](#tec-codes).)
|
||||
|
||||
You can create an offer so long as you have at least some (any positive, nonzero amount) of the currency specified by the `TakerGets` parameter of the offer. The offer sells as much of the currency as you have, up to the `TakerGets` amount, until the `TakerPays` amount is satisfied. An offer cannot place anyone in debt.
|
||||
|
||||
It is possible for an offer to become temporarily or permanently _unfunded_:
|
||||
|
||||
* If the creator no longer has any of the `TakerGets` currency.
|
||||
* The offer becomes funded again when the creator obtains more of that currency.
|
||||
* If the currency required to fund the offer is held in a [frozen trust line](concept-freeze.html).
|
||||
* The offer becomes funded again when the trust line is no longer frozen.
|
||||
* If the creator does not have enough XRP for the reserve amount of a new trust line required by the offer. (See [Offers and Trust](#offers-and-trust).)
|
||||
* The offer becomes funded again when the creator obtains more XRP, or the reserve requirements decrease.
|
||||
* If the Expiration time included in the offer is before the close time of the most recently-closed ledger. (See [Expiration](#expiration).)
|
||||
|
||||
An unfunded offer can stay on the ledger indefinitely, but it does not have any effect. The only ways an offer can be *permanently* removed from the ledger are:
|
||||
|
||||
* It becomes fully claimed by a Payment or a matching OfferCreate transaction.
|
||||
* An OfferCancel or OfferCreate transaction explicitly cancels the offer.
|
||||
* An OfferCreate transaction from the same account crosses the earlier offer. (In this case, the older offer is automatically canceled.)
|
||||
* An offer is found to be unfunded during transaction processing, typically because it was at the tip of the orderbook.
|
||||
* This includes cases where one side or the other of an offer is found to be closer to 0 than `rippled`'s precision supports.
|
||||
|
||||
### Tracking Unfunded Offers
|
||||
|
||||
Tracking the funding status of all offers can be computationally taxing. In particular, addresses that are actively trading may have a large number of offers open. A single balance can affect the funding status of many offers to buy different currencies. Because of this, `rippled` does not proactively find and remove offers.
|
||||
|
||||
A client application can locally track the funding status of offers. To do this, first retreive an order book using the [book_offers method][] and check the `taker_gets_funded` field of offers. Then, [subscribe](reference-rippled.html#subscribe) to the `transactions` stream and watch the transaction metadata to see which offers are modified.
|
||||
|
||||
|
||||
## Offers and Trust
|
||||
|
||||
The limit values of trust lines (See [TrustSet](#trustset)) do not affect offers. In other words, you can use an offer to acquire more than the maximum amount you trust an issuer to redeem.
|
||||
|
||||
However, holding non-XRP balances still requires a trust line to the address issuing those balances. When an offer is taken, it automatically creates any necessary trust lines, setting their limits to 0. Because [trust lines increase the reserve an account must hold](concept-reserves.html), any offers that would require a new trust line also require the address to have enough XRP to meet the reserve for that trust line.
|
||||
|
||||
A trust line indicates an issuer you trust enough to accept their issuances as payment, within limits. Offers are explicit instructions to acquire certain issuances, so they are allowed to go beyond those limits.
|
||||
|
||||
## Offer Preference
|
||||
|
||||
Existing offers are grouped by exchange rate (sometimes called "offer quality"), which is measured as the ratio between `TakerGets` and `TakerPays`. Offers with a higher exchange rate are taken preferentially. (That is, the person accepting the offer receives as much as possible for the amount of currency they pay out.) Offers with the same exchange rate are taken on the basis of which offer was placed in the earliest ledger version.
|
||||
|
||||
When offers of the same exchange rate are placed in the same ledger version, the order in which they are taken is determined by the [canonical order](https://github.com/ripple/rippled/blob/release/src/ripple/app/misc/CanonicalTXSet.cpp "Source: Transaction ordering") in which the transactions were [applied to the ledger](https://github.com/ripple/rippled/blob/5425a90f160711e46b2c1f1c93d68e5941e4bfb6/src/ripple/app/consensus/LedgerConsensus.cpp#L1435-L1538 "Source: Applying transactions"). This behavior is designed to be deterministic, efficient, and hard to game.
|
||||
|
||||
### TickSize
|
||||
|
||||
_Requires the [TickSize amendment](reference-amendments.html#ticksize)._
|
||||
|
||||
When an Offer is placed into an order book, its exchange rate is truncated based on the `TickSize` values set by the issuers of the currencies involved in the Offer. When a trader offers to exchange XRP and an issued currency, the `TickSize` from the issuer of the currency applies. When a trader offers to exchange two issued currencies, the offer uses the smaller `TickSize` value (that is, the one with fewer significant digits). If neither currency has a `TickSize` set, the default behavior applies.
|
||||
|
||||
The `TickSize` value truncates the number of _significant digits_ in the exchange rate of an offer when it gets placed in an order book. Issuers can set `TickSize` to an integer from `3` to `15` using an [AccountSet transaction][]. The exchange rate is represented as significant digits and an exponent; the `TickSize` does not affect the exponent. This allows the XRP Ledger to represent exchange rates between assets that vary greatly in value (for example, a hyperinflated currency compared to a rare commodity). The lower the `TickSize` an issuer sets, the larger the increment traders must offer to be considered a higher exchange rate than the existing Offers.
|
||||
|
||||
The `TickSize` does not affect the part of an Offer that can be executed immediately. (For that reason, OfferCreate transactions with `tfImmediateOrCancel` are unaffected by `TickSize` values.) If the Offer cannot be fully executed, the transaction processing engine calculates the exchange rate and truncates it based on `TickSize`. Then, the engine rounds the remaining amount of the Offer from the "less important" side to match the truncated exchange rate. For a default OfferCreate transaction (a "buy" Offer), the `TakerPays` amount (the amount being bought) gets rounded. If the `tfSell` flag is enabled (a "sell" Offer) the `TakerGets` amount (the amount being sold) gets rounded.
|
||||
|
||||
When an issuer enables, disables, or changes the `TickSize`, Offers that were placed under the previous setting are unaffected.
|
||||
|
||||
|
||||
## Expiration
|
||||
|
||||
Since transactions can take time to propagate and confirm, the timestamp of a ledger is used to determine offer validity. An offer only expires when its Expiration time is before the most-recently validated ledger. In other words, an offer with an `Expiration` field is still considered "active" if its expiration time is later than the timestamp of the most-recently validated ledger, regardless of what your local clock says.
|
||||
|
||||
You can determine the final disposition of an offer with an `Expiration` as soon as you see a fully-validated ledger with a close time equal to or greater than the expiration time.
|
||||
|
||||
**Note:** Since only new transactions can modify the ledger, an expired offer can stay on the ledger after it becomes inactive. The offer is treated as unfunded and has no effect, but it can continue to appear in results (for example, from the [ledger_entry](reference-rippled.html#ledger-entry) command). Later on, the expired offer can get finally deleted as a result of another transaction (such as another OfferCreate) if the server finds it while processing.
|
||||
|
||||
If an OfferCreate transaction has an `Expiration` time that has already passed when the transaction first gets included in a ledger, the transaction does not execute the offer. The result code of such a transaction depends on whether the [Checks amendment](reference-amendments.html#checks) is enabled. With the Checks amendment enabled, the transaction has the `tecEXPIRED` result code. Otherwise, the transaction has the `tesSUCCESS` transaction code. In either case, the transaction has no effect except to destroy the XRP paid as a [transaction cost](concept-transaction-cost.html).
|
||||
|
||||
## Auto-Bridging
|
||||
|
||||
Any OfferCreate that would exchange two non-XRP currencies could potentially use XRP as an intermediary currency in a synthetic order book. This is because of auto-bridging, which serves to improve liquidity across all currency pairs by using XRP as a vehicle currency. This works because of XRP's nature as a native cryptocurrency to the XRP Ledger. Offer execution can use a combination of direct and auto-bridged offers to achieve the best total exchange rate.
|
||||
|
||||
Example: _Anita places an offer to sell GBP and buy BRL. She might find that this uncommon currency market has few offers. There is one offer with a good rate, but it has insufficient quantity to satisfy Anita's trade. However, both GBP and BRL have active, competitive markets to XRP. Auto-bridging software finds a way to complete Anita's offer by purchasing XRP with GBP from one trader, then selling the XRP to another trader to buy BRL. Anita automatically gets the best rate possible by combining the small offer in the direct GBP:BRL market with the better composite rates created by pairing GBP:XRP and XRP:BRL offers._
|
||||
|
||||
Auto-bridging happens automatically on any OfferCreate transaction. [Payment transactions](#payment) _do not_ autobridge by default, but path-finding can find paths that have the same effect.
|
||||
23
content/concepts/the-rippled-server/clustering.md
Normal file
23
content/concepts/the-rippled-server/clustering.md
Normal file
@@ -0,0 +1,23 @@
|
||||
# Clustering
|
||||
|
||||
If you are running multiple [`rippled` servers](the-rippled-server.html) in a single datacenter, you can configure those servers into a cluster to maximize efficiency. Running your `rippled` servers in a cluster provides the following benefits:
|
||||
|
||||
- Clustered `rippled` servers share the work of cryptography. If one server has verified the authenticity of a message, the other servers in the cluster trust it and do not re-verify.
|
||||
- Clustered servers share information about peers and API clients that are misbehaving or abusing the network. This makes it harder to attack all servers of the cluster at once.
|
||||
- Clustered servers always propagate transactions throughout the cluster, even if the transaction does not meet the current load-based transaction fee on some of them.
|
||||
|
||||
If you are running a validator as a [private peer](peer-protocol.html#private-peers), Ripple recommends using a cluster of `rippled` servers as proxy servers.
|
||||
|
||||
## Configuring Clustering
|
||||
|
||||
To enable clustering, change the following sections of your [config file](https://github.com/ripple/rippled/blob/d7def5509d8338b1e46c0adf309b5912e5168af0/doc/rippled-example.cfg#L297-L346) for each server:
|
||||
|
||||
1. List the IP address and port of each other server under the `[ips_fixed]` section. The port should be the one from the other servers' `protocol = peer` setting in their `rippled.cfg`. Example:
|
||||
|
||||
[ips_fixed]
|
||||
192.168.0.1 51235
|
||||
192.168.0.2 51235
|
||||
|
||||
2. Generate a unique seed (using the [validation_create method][]) for each of your servers, and configure it under the `[node_seed]` section. The `rippled` server uses this key to sign its messages to other servers in the peer-to-peer network.
|
||||
|
||||
3. Add each node's peer-communication public key (generated in step 2) to the `[cluster_nodes]` section of each of your other servers' config files.
|
||||
177
content/concepts/the-rippled-server/peer-protocol.md
Normal file
177
content/concepts/the-rippled-server/peer-protocol.md
Normal file
@@ -0,0 +1,177 @@
|
||||
# Peer Protocol
|
||||
|
||||
Servers in the XRP Ledger communicate to each other using the XRP Ledger peer protocol, also known as RTXP. Peer servers connect via HTTPS and then do an [HTTP upgrade](https://tools.ietf.org/html/rfc7230#section-6.7) to switch to RTXP. (For more information, see the [Overlay Network](https://github.com/ripple/rippled/blob/906ef761bab95f80b0a7e0cab3b4c594b226cf57/src/ripple/overlay/README.md#handshake) article in the [`rippled` repository](https://github.com/ripple/rippled).)
|
||||
|
||||
## Configuring the Peer Protocol
|
||||
|
||||
To participate in the XRP Ledger, `rippled` servers connects to arbitrary peers using the peer protocol. (All such peers are treated as untrusted, unless they are [clustered](tutorial-rippled-setup.html#clustering) with the current server.)
|
||||
|
||||
Ideally, the server should be able to send _and_ receive connections on the peer port. You should forward the port used for the peer protocol through your firewall to the `rippled` server. The [default `rippled` configuration file](https://github.com/ripple/rippled/blob/release/doc/rippled-example.cfg) listens for incoming peer protocol connections on port 51235 on all network interfaces. You can change the port used by editing the appropriate stanza in your `rippled.cfg` file.
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
[port_peer]
|
||||
port = 51235
|
||||
ip = 0.0.0.0
|
||||
protocol = peer
|
||||
```
|
||||
|
||||
## Peer Crawler
|
||||
|
||||
The Peer Crawler asks a `rippled` server to report information about the other `rippled` servers it is connected to as peers. The [`peers` command](#peers) in the [WebSocket and JSON-RPC APIs](#websocket-and-json-rpc-apis) also returns a similar, more comprehensive set of information, but requires [administrative access](#connecting-to-rippled) to the server. The Peer Crawler response is available to other servers on a non-privileged basis through the Peer Protocol (RTXP) port.
|
||||
|
||||
#### Request Format
|
||||
|
||||
To request the Peer Crawler information, make the following HTTP request:
|
||||
|
||||
* **Protocol:** https
|
||||
* **HTTP Method:** GET
|
||||
* **Host:** (any `rippled` server, by hostname or IP address)
|
||||
* **Port:** (port number where the `rippled` server uses the Peer Protocol, typically 51235)
|
||||
* **Path:** `/crawl`
|
||||
* **Notes:** Most `rippled` servers use a self-signed certificate to respond to the request. By default, most tools (including web browsers) flag or block such responses for being untrusted. You must ignore the certificate checking (for example, if using cURL, add the `--insecure` flag) to display a response from those servers.
|
||||
|
||||
#### Response Format
|
||||
|
||||
The response has the status code **200 OK** and a JSON object in the message body.
|
||||
|
||||
The JSON object has the following fields:
|
||||
|
||||
| `Field` | Value | Description |
|
||||
|:-----------------|:------|:--------------------------------------------------|
|
||||
| `overlay.active` | Array | Array of Peer Objects, where each member is a peer that is connected to this server. |
|
||||
|
||||
Each member of the `active` array is a Peer Object with the following fields:
|
||||
|
||||
| `Field` | Value | Description |
|
||||
|:-------------|:-------------------------|:-----------------------------------|
|
||||
| `ip` | String (IPv4 Address) | The IP address of this connected peer. |
|
||||
| `port` | String (Number) | The port number on the peer server that serves RTXP. Typically 51235. |
|
||||
| `public_key` | String (Base-64 Encoded) | The public key of the ECDSA key pair used by this peer to sign RTXP messages. (This is the same data as the `pubkey_node` reported in the peer server's [`server_info` command](#server-info).) |
|
||||
| `type` | String | The value `in` or `out`, indicating whether the TCP connection to the peer is incoming or outgoing. |
|
||||
| `uptime` | Number | The number of seconds the server has been has been connected to this peer. |
|
||||
| `version` | String | The `rippled` version number the peer reports to be using. |
|
||||
|
||||
#### Example
|
||||
|
||||
Request:
|
||||
|
||||
<!-- MULTICODE_BLOCK_START -->
|
||||
|
||||
*HTTP*
|
||||
|
||||
```
|
||||
GET https://s1.ripple.com:51235/crawl
|
||||
```
|
||||
|
||||
*cURL*
|
||||
|
||||
```
|
||||
curl -k https://s1.ripple.com:51235/crawl
|
||||
```
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
Response:
|
||||
|
||||
```json
|
||||
200 OK
|
||||
{
|
||||
"overlay": {
|
||||
"active": [{
|
||||
"ip": "208.43.252.243",
|
||||
"port": "51235",
|
||||
"public_key": "A2GayQNaj7qbqLFiCFW2UXtAnEPghP/KWVqix2gUa6dM",
|
||||
"type": "out",
|
||||
"uptime": 107926,
|
||||
"version": "rippled-0.31.0-rc1"
|
||||
}, {
|
||||
"ip": "184.172.237.226",
|
||||
"port": "51235",
|
||||
"public_key": "Asv/wKq/dqMWbP2M4eR+QvkuojYMLRXhKhIPnW40bsaF",
|
||||
"type": "out",
|
||||
"uptime": 247376,
|
||||
"version": "rippled-0.31.0-rc1"
|
||||
}, {
|
||||
"ip": "54.186.73.52",
|
||||
"port": "51235",
|
||||
"public_key": "AjikFnq0P2XybCyREr2KPiqXqJteqwPwVRVbVK+93+3o",
|
||||
"type": "out",
|
||||
"uptime": 328776,
|
||||
"version": "rippled-0.31.0-rc1"
|
||||
}, {
|
||||
"ip": "169.53.155.59",
|
||||
"port": "51235",
|
||||
"public_key": "AyIcVhAhOGnP0vtfCt+HKUrx9B2fDvP/4XUkOtVQ37g/",
|
||||
"type": "out",
|
||||
"uptime": 328776,
|
||||
"version": "rippled-0.31.1"
|
||||
}, {
|
||||
"ip": "169.53.155.44",
|
||||
"port": "51235",
|
||||
"public_key": "AuVZszWXgMgM8YuTVhQsGE9OciEeBD8aMVe1mFid3n63",
|
||||
"type": "out",
|
||||
"uptime": 328776,
|
||||
"version": "rippled-0.32.0-b12"
|
||||
}, {
|
||||
"ip": "184.173.45.39",
|
||||
"port": "51235",
|
||||
"public_key": "Ao2GbGbp2QYQ2B4S9ckCtON7CsZdXqdK5Yon4x7qmWFm",
|
||||
"type": "out",
|
||||
"uptime": 63336,
|
||||
"version": "rippled-0.31.0-rc1"
|
||||
}, {
|
||||
"ip": "169.53.155.34",
|
||||
"port": "51235",
|
||||
"public_key": "A3inNJsIQzO7z7SS7uB9DyvN0wsiS9it/RGY/kNx6KEG",
|
||||
"type": "out",
|
||||
"uptime": 328776,
|
||||
"version": "rippled-0.31.0-rc1"
|
||||
}, {
|
||||
"ip": "169.53.155.45",
|
||||
"port": "51235",
|
||||
"public_key": "AglUUjwXTC2kUlK41WjDs2eAVN0SnlMpzYA9lEgB0UGP",
|
||||
"type": "out",
|
||||
"uptime": 65443,
|
||||
"version": "rippled-0.31.0-rc1"
|
||||
}, {
|
||||
"ip": "99.110.49.91",
|
||||
"port": "51301",
|
||||
"public_key": "AuQDH0o+4fpl2n+pR5U0Y4FTj0oGr4iEKe0MObPcSYj9",
|
||||
"type": "out",
|
||||
"uptime": 328776,
|
||||
"version": "rippled-0.32.0-b9"
|
||||
}, {
|
||||
"ip": "169.53.155.36",
|
||||
"port": "51235",
|
||||
"public_key": "AsR4xub7MLg2Zl5Fwd/n7dTz7mhbBoSyCc/v9bnubrVy",
|
||||
"type": "out",
|
||||
"uptime": 328776,
|
||||
"version": "rippled-0.31.0-rc1"
|
||||
}]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Private Peers
|
||||
|
||||
<!--{# TODO: unify with the very similar "Public-Facing Server" section of rippled-setup and probably move to a tutorial #}-->
|
||||
|
||||
You can use the `[peer_private]` stanza of the `rippled` config file to request that peer servers do not report your IP address in the Peer Crawler response. Servers you do not control can be modified not to respect this setting. However, you can use this to hide the IP addresses of `rippled` servers you control that _only_ connect to peers you control (using `[ips_fixed]` and a firewall). In this way, you can use public rippled servers you control as proxies for your private rippled servers.
|
||||
|
||||
To protect an important [validating server](tutorial-rippled-setup.html#types-of-rippled-servers), Ripple recommends configuring one or more public tracking servers to act as proxies, while the validating server is protected by a firewall and only connects to the public tracking servers.
|
||||
|
||||
<!--{# TODO: network diagram of private peers #}-->
|
||||
|
||||
Example configuration:
|
||||
|
||||
```
|
||||
# Configuration on a private server that only connects through
|
||||
# a second rippled server at IP address 10.1.10.55
|
||||
[ips_fixed]
|
||||
10.1.10.55
|
||||
|
||||
[peer_private]
|
||||
1
|
||||
```
|
||||
@@ -2,18 +2,6 @@
|
||||
|
||||
`rippled` is the core peer-to-peer server that manages the XRP Ledger. This section covers concepts that help you learn the "what" and "why" behind fundamental aspects of the `rippled` server.
|
||||
|
||||
Other pages in this category:
|
||||
|
||||
* **[History Sharding](history-sharding.html)**
|
||||
|
||||
Historical sharding distributes the transaction history of the XRP Ledger into segments, called shards, across servers in the XRP Ledger network. Understand the purpose of history sharding and when to use it.
|
||||
<!--{# TODO: Is this History Sharding or Historical Sharding? #}-->
|
||||
|
||||
* **[Clustering](clustering.html)**
|
||||
|
||||
If you are running multiple `rippled` servers in a single datacenter, you can configure those servers into a cluster to maximize efficiency. Understand the purpose of clustering and when to use it.
|
||||
|
||||
|
||||
## Types of rippled Servers
|
||||
|
||||
The `rippled` server software can run in several modes depending on its configuration, including:
|
||||
|
||||
Reference in New Issue
Block a user