mirror of
https://github.com/XRPLF/xrpl-dev-portal.git
synced 2025-11-04 20:05:50 +00:00
Reorg: remove generated HTML files, move dactyl-config to op level (#270)
* Reorg: remove generated HTML files, move dactyl-config to op level * Update CI for reorg
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -3,3 +3,4 @@
|
||||
.DS_Store
|
||||
content/code_samples/*/node_modules/
|
||||
__pycache__
|
||||
out/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
general:
|
||||
build_dir: tool/
|
||||
build_dir: ./
|
||||
dependencies:
|
||||
pre:
|
||||
- pyenv global 3.4.0
|
||||
@@ -7,5 +7,5 @@ dependencies:
|
||||
- pip3 install dactyl
|
||||
test:
|
||||
override:
|
||||
- dactyl_build
|
||||
- dactyl_build -s
|
||||
- dactyl_link_checker
|
||||
|
||||
@@ -1,331 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<meta name="viewport" content="width=device-width">
|
||||
|
||||
<title>Accounts - Ripple Developer Portal</title>
|
||||
|
||||
<!-- favicon -->
|
||||
<link rel="icon" href="favicon.ico" type="image/x-icon">
|
||||
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon">
|
||||
|
||||
<!-- jQuery -->
|
||||
<script src="assets/vendor/jquery-1.11.1.min.js"></script>
|
||||
|
||||
<!-- Custom Stylesheets. ripple.css includes bootstrap, font stuff -->
|
||||
<link href="assets/css/ripple.css" rel="stylesheet" />
|
||||
<link href="assets/css/devportal.css" rel="stylesheet" />
|
||||
|
||||
<!-- Bootstrap JS -->
|
||||
<script src="assets/vendor/bootstrap.min.js"></script>
|
||||
|
||||
|
||||
<!-- syntax highlighting -->
|
||||
<link rel="stylesheet" href="assets/vendor/docco.min.css" />
|
||||
<script src="assets/vendor/highlight.min.js"></script>
|
||||
|
||||
<!-- syntax selection js -->
|
||||
<script src="assets/js/multicodetab.js"></script>
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
$(".multicode").minitabs();
|
||||
hljs.initHighlighting();
|
||||
make_code_expandable();
|
||||
});
|
||||
</script>
|
||||
|
||||
<script src="assets/js/expandcode.js"></script>
|
||||
<script src="assets/js/fixsidebarscroll.js"></script>
|
||||
|
||||
<!-- fontawesome icons -->
|
||||
<link rel="stylesheet" href="assets/vendor/fontawesome/css/font-awesome.min.css" />
|
||||
|
||||
</head>
|
||||
|
||||
<body class="page page-template page-template-template-dev-portal page-template-template-dev-portal-php sidebar-primary wpb-js-composer js-comp-ver-3.6.2 vc_responsive">
|
||||
<header role="banner" class="banner navbar navbar-default navbar-fixed-top initial_header">
|
||||
<div class="container">
|
||||
<div class="navbar-header">
|
||||
<a href="index.html" class="navbar-brand"><img src="assets/img/ripple-logo-color.png" class="logo"></a>
|
||||
</div><!-- /.navbar-header -->
|
||||
<div class="nav">
|
||||
<div class="draft-warning">DRAFT PAGE</div>
|
||||
</div><!-- /.nav -->
|
||||
|
||||
</div><!-- /.container -->
|
||||
|
||||
<div class="subnav dev_nav">
|
||||
<div class="container">
|
||||
<ul id="menu-dev-menu" class="menu">
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">References <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="reference-rippleapi.html">RippleAPI</a></li>
|
||||
<li><a href="reference-rippled.html">rippled</a></li>
|
||||
<li><a href="reference-transaction-format.html">Transaction Format</a></li>
|
||||
<li><a href="reference-ledger-format.html">Ledger Format</a></li>
|
||||
<li><a href="reference-data-api.html">Ripple Data API v2</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorials <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="tutorial-multisign.html">How to Multi-Sign</a></li>
|
||||
<li><a href="tutorial-paychan.html">Payment Channels Tutorial</a></li>
|
||||
<li><a href="concept-issuing-and-operational-addresses.html">Issuing and Operational Addresses</a></li>
|
||||
<li><a href="tutorial-reliable-transaction-submission.html">Reliable Transaction Submission</a></li>
|
||||
<li><a href="tutorial-rippleapi-beginners-guide.html">RippleAPI Beginners Guide</a></li>
|
||||
<li><a href="tutorial-rippled-setup.html">rippled Setup</a></li>
|
||||
<li><a href="tutorial-gateway-guide.html">Gateway Guide</a></li>
|
||||
<li><a href="tutorial-listing-xrp.html">Listing XRP as an Exchange</a></li>
|
||||
<li><a href="tutorial-escrow.html">Escrow Tutorials</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Features <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="concept-accounts.html">Accounts</a></li>
|
||||
<li><a href="concept-amendments.html">Amendments</a></li>
|
||||
<li><a href="concept-consensus.html">Consensus Process</a></li>
|
||||
<li><a href="concept-reaching-consensus.html">Reaching Consensus in the XRP Ledger</a></li>
|
||||
<li><a href="concept-fee-voting.html">Fee Voting</a></li>
|
||||
<li><a href="concept-fees.html">Fees (Disambiguation)</a></li>
|
||||
<li><a href="concept-freeze.html">Freeze</a></li>
|
||||
<li><a href="concept-partial-payments.html">Partial Payments</a></li>
|
||||
<li><a href="concept-paths.html">Paths</a></li>
|
||||
<li><a href="concept-reserves.html">Reserves</a></li>
|
||||
<li><a href="concept-stand-alone-mode.html">Stand-Alone Mode</a></li>
|
||||
<li><a href="concept-transaction-cost.html">Transaction Cost</a></li>
|
||||
<li><a href="concept-transfer-fees.html">Transfer Fees</a></li>
|
||||
<li><a href="concept-noripple.html">Understanding the NoRipple flag</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Gateway Bulletins <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="gb-2015-06.html">GB-2015-06: Corrections to Autobridging</a></li>
|
||||
<li><a href="gb-2015-05.html">GB-2015-05: Historical Ledger Query Migration</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">API Tools <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="ripple-api-tool.html">WebSocket API Tool</a></li>
|
||||
<li><a href="data-api-v2-tool.html">Data API v2 Tool</a></li>
|
||||
<li><a href="tool-jsonrpc.html">rippled JSON-RPC Tool</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li><a href="https://github.com/ripple/ripple-dev-portal" title="GitHub">Site Source</a></li>
|
||||
</ul><!-- /#dev-menu -->
|
||||
</div><!-- /.subnav .container -->
|
||||
</div><!-- /.subnav -->
|
||||
</header>
|
||||
|
||||
|
||||
<div class="wrap container" role="document">
|
||||
<aside class="sidebar" role="complementary">
|
||||
<div class="dev_nav_wrapper">
|
||||
<div id="cont">
|
||||
<h5>In this category:</h5>
|
||||
<ul class="dev_nav_sidebar">
|
||||
<li class="level-1"><a href="index.html">Category: Features</a></li>
|
||||
<li class="level-2"><a href="concept-accounts.html">Accounts</a></li>
|
||||
<li class="level-2"><a href="concept-amendments.html">Amendments</a></li>
|
||||
<li class="level-2"><a href="concept-consensus.html">Consensus Process</a></li>
|
||||
<li class="level-2"><a href="concept-reaching-consensus.html">Reaching Consensus in the XRP Ledger</a></li>
|
||||
<li class="level-2"><a href="concept-fee-voting.html">Fee Voting</a></li>
|
||||
<li class="level-2"><a href="concept-fees.html">Fees (Disambiguation)</a></li>
|
||||
<li class="level-2"><a href="concept-freeze.html">Freeze</a></li>
|
||||
<li class="level-2"><a href="concept-partial-payments.html">Partial Payments</a></li>
|
||||
<li class="level-2"><a href="concept-paths.html">Paths</a></li>
|
||||
<li class="level-2"><a href="concept-reserves.html">Reserves</a></li>
|
||||
<li class="level-2"><a href="concept-stand-alone-mode.html">Stand-Alone Mode</a></li>
|
||||
<li class="level-2"><a href="concept-transaction-cost.html">Transaction Cost</a></li>
|
||||
<li class="level-2"><a href="concept-transfer-fees.html">Transfer Fees</a></li>
|
||||
<li class="level-2"><a href="concept-noripple.html">Understanding the NoRipple flag</a></li>
|
||||
</ul>
|
||||
<hr />
|
||||
<h5>In this page:</h5>
|
||||
<ul class="dev_nav_sidebar" id="dactyl_toc_sidebar">
|
||||
<li class="level-1"><a href="#xrp-ledger-accounts">XRP Ledger Accounts</a></li>
|
||||
<li class="level-2"><a href="#addresses">Addresses</a></li>
|
||||
<li class="level-3"><a href="#special-addresses">Special Addresses</a></li>
|
||||
<li class="level-2"><a href="#permanence-of-accounts">Permanence of Accounts</a></li>
|
||||
<li class="level-2"><a href="#transaction-history">Transaction History</a></li>
|
||||
<li class="level-2"><a href="#address-encoding">Address Encoding</a></li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
<main class="main" role="main">
|
||||
<div class='content'>
|
||||
<h1 id="xrp-ledger-accounts">XRP Ledger Accounts</h1>
|
||||
<p>An "Account" in the XRP Ledger represents a holder of XRP and a sender of <a href="reference-transaction-format.html">transactions</a>. The core elements of an account are:</p>
|
||||
<ul>
|
||||
<li>An identifying <strong>address</strong>, such as <code>rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn</code></li>
|
||||
<li>An <strong>XRP balance</strong>. Some of this XRP is set aside for the <a href="concept-reserves.html">Reserve</a>.</li>
|
||||
<li>A <strong>sequence number</strong>, starting at 1 and increasing with each transaction sent from this account. No transaction can be included in a ledger unless the transaction's sequence number matches its sender's next sequence number.</li>
|
||||
<li>A <strong>history of transactions</strong> that affected this account and its balances.</li>
|
||||
<li>One or more ways to <a href="reference-transaction-format.html#authorizing-transactions">authorize transactions</a>, possibly including:<ul>
|
||||
<li>A master key pair intrinsic to the account. (This can be <a href="reference-transaction-format.html#accountset-flags">disabled</a> but not changed.)</li>
|
||||
<li>A "regular" key pair that <a href="reference-transaction-format.html#setregularkey">can be rotated</a>.</li>
|
||||
<li>A signer list for <a href="reference-transaction-format.html#multi-signing">multi-signing</a>. (Stored separately from the account's core data.)</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<p>In the ledger's data tree, an account's core data is stored in the <a href="reference-ledger-format.html#accountroot">AccountRoot</a> ledger node type. An account can also be the owner (or partial owner) of several other types of data.</p>
|
||||
<p class="devportal-callout tip"><strong>Tip:</strong> An "Account" in the XRP Ledger is somewhere between the financial usage (like "bank account") and the computing usage (like "UNIX account"). Non-XRP currencies and assets aren't stored in an XRP Ledger Account itself; each such asset is stored in an accounting relationship called a "Trust Line" that connects two parties.</p>
|
||||
<h2 id="addresses">Addresses</h2>
|
||||
<p>Accounts in the XRP Ledger are identified by a base58 XRP Ledger Address. The address is derived from the account's master <a href="https://en.wikipedia.org/wiki/Public-key_cryptography">public key</a>, which is in turn derived from a secret key. An address is represented as a string in JSON and has the following characteristics:</p>
|
||||
<ul>
|
||||
<li>Between 25 and 35 characters in length</li>
|
||||
<li>Starts with the character <code>r</code></li>
|
||||
<li>Uses alphanumeric characters, excluding the number "<code>0</code>" capital letter "<code>O</code>", capital letter "<code>I</code>", and lowercase letter "<code>l</code>"</li>
|
||||
<li>Case-sensitive</li>
|
||||
<li>Includes a 4-byte checksum so that the probability of generating a valid address from random characters is approximately 1 in 2^32</li>
|
||||
</ul>
|
||||
<p>Any valid address can become an account in the XRP Ledger by receiving a <a href="reference-transaction-format.html#payment">Payment</a> of XRP, as long as the amount of XRP delivered is greater than or equal to the <a href="concept-reserves.html">account reserve</a>. This is called <em>funding</em> the account. You can also use an address that has not been funded to represent a <a href="reference-transaction-format.html#setregularkey">regular key</a> or a member of a <a href="reference-transaction-format.html#multi-signing">signer list</a>. Only a funded account can be the sender of a transaction.</p>
|
||||
<p>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 <em>and</em> the address of the sender.)</p>
|
||||
<p>For more technical details of how to calculate an XRP Ledger address, see <a href="#address-encoding">Address Encoding</a>.</p>
|
||||
<h3 id="special-addresses">Special Addresses</h3>
|
||||
<p>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.</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Address</th>
|
||||
<th>Name</th>
|
||||
<th>Meaning</th>
|
||||
<th>Black Hole?</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>rrrrrrrrrrrrrrrrrrrrrhoLvTp</td>
|
||||
<td>ACCOUNT_ZERO</td>
|
||||
<td>An address that is the base58 encoding of the value <code>0</code>. In peer-to-peer communications, <code>rippled</code> uses this address as the issuer for XRP.</td>
|
||||
<td>Yes</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>rrrrrrrrrrrrrrrrrrrrBZbvji</td>
|
||||
<td>ACCOUNT_ONE</td>
|
||||
<td>An address that is the base58 encoding of the value <code>1</code>. In the ledger, <a href="reference-ledger-format.html#ripplestate">RippleState entries</a> use this address as a placeholder for the issuer of a trust line balance.</td>
|
||||
<td>Yes</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh</td>
|
||||
<td>The genesis account</td>
|
||||
<td>When <code>rippled</code> 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 <a href="https://github.com/ripple/rippled/blob/94ed5b3a53077d815ad0dd65d490c8d37a147361/src/ripple/app/ledger/Ledger.cpp#L184">hard-coded</a>.</td>
|
||||
<td>No</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>rrrrrrrrrrrrrrrrrNAMEtxvNvQ</td>
|
||||
<td>Ripple Name reservation black-hole</td>
|
||||
<td>In the past, Ripple asked users to send XRP to this account to reserve Ripple Names.</td>
|
||||
<td>Yes</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>rrrrrrrrrrrrrrrrrrrn5RM1rHd</td>
|
||||
<td>NaN Address</td>
|
||||
<td>Previous versions of <a href="https://github.com/ripple/ripple-lib">ripple-lib</a> generated this address when base58 encoding the value <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/NaN">NaN</a>.</td>
|
||||
<td>Yes</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h2 id="permanence-of-accounts">Permanence of Accounts</h2>
|
||||
<p>Once created, an account exists in the XRP Ledger's data tree forever. This is because the current sequence number for a transaction must be tracked forever, so that old transactions cannot be processed a second time.</p>
|
||||
<p>Unlike Bitcoin and many other crypto-currencies, 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, Ripple discourages creating new accounts unless entirely necessary. Institutions who send and receive value on behalf of many users can use <a href="tutorial-gateway-guide.html#source-and-destination-tags"><strong>Source Tags</strong> and <strong>Destination Tags</strong></a> to distinguish payments from and to their customers while only using one (or a handful) of accounts in the XRP Ledger.</p>
|
||||
<h2 id="transaction-history">Transaction History</h2>
|
||||
<p>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 <code>AccountRoot</code> ledger node 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 <code>AccountRoot</code> 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 <code>AccountRoot</code> node directly, including:</p>
|
||||
<ul>
|
||||
<li>Transactions sent by the account, because they modify the account's <code>Sequence</code> number. These transactions also modify the account's XRP balance because of the <a href="concept-transaction-cost.html">transaction cost</a>.</li>
|
||||
<li>Transactions that modified the account's XRP balance, including incoming <a href="reference-transaction-format.html#payment">Payment transactions</a> and other types of transactions such as <a href="reference-transaction-format.html#paymentchannelclaim">PaymentChannelClaim</a> and <a href="reference-transaction-format.html#escrowfinish">EscrowFinish</a>.</li>
|
||||
</ul>
|
||||
<p>The <em>conceptual</em> transaction history of an account also includes transactions that modified the account's owned objects and non-XRP balances. These objects are separate ledger nodes, 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 node objects created or modified by it. A "complete" transaction history includes the history of objects owned by a transaction, such as:</p>
|
||||
<ul>
|
||||
<li><code>RippleState</code> objects (Trust Lines) connected to the account.</li>
|
||||
<li><code>DirectoryNode</code> objects, especially the owner directory tracking the account's owned objects.</li>
|
||||
<li><code>Offer</code> objects, representing the account's outstanding currency-exchange orders in the decentralized exchange</li>
|
||||
<li><code>PayChannel</code> objects, representing asynchronous payment channels to and from the account</li>
|
||||
<li><code>Escrow</code> objects, representing held payments to or from the account that are locked by time or a crypto-condition.</li>
|
||||
<li><code>SignerList</code> objects, representing lists of addresses that can authorize transactions for the account by <a href="reference-transaction-format.html#multi-signing">multi-signing</a>.</li>
|
||||
</ul>
|
||||
<p>For more information on each of these objects, see the <a href="reference-ledger-format.html">Ledger Format Reference</a>.</p>
|
||||
<h2 id="address-encoding">Address Encoding</h2>
|
||||
<p class="devportal-callout tip"><strong>Tip:</strong> These technical details are only relevant for people building low-level library software for XRP Ledger compatibility!</p>
|
||||
<p><a href="https://github.com/ripple/rippled/blob/35fa20a110e3d43ffc1e9e664fc9017b6f2747ae/src/ripple/protocol/impl/AccountID.cpp#L109-L140" title="Source">[Source]<br/></a></p>
|
||||
<p>XRP Ledger addresses are encoded using <a href="https://en.wikipedia.org/wiki/Base58">base58</a> with the Ripple <em>dictionary</em>: <code>rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz</code>. 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.</p>
|
||||
<p>The following diagram shows the relationship between keys and addresses:</p>
|
||||
<p><img alt="Passphrase → Secret Key → Public Key + Type Prefix → Account ID + Checksum → Address" src="img/key-address-rels.png"/></p>
|
||||
<p>The formula for calculating an XRP Ledger address is as follows. For the complete example code, see <a href="https://github.com/ripple/ripple-dev-portal/blob/master/content/code_samples/address_encoding/encode_address.js"><code>encode_address.js</code></a>.</p>
|
||||
<ol>
|
||||
<li>
|
||||
<p>Import required algorithms: SHA-256, RIPEMD160, and base58. Set the dictionary for base58.</p>
|
||||
<pre><code>'use strict';
|
||||
const assert = require('assert');
|
||||
const crypto = require('crypto');
|
||||
const R_B58_DICT = 'rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz';
|
||||
const base58 = require('base-x')(R_B58_DICT);
|
||||
|
||||
assert(crypto.getHashes().includes('sha256'));
|
||||
assert(crypto.getHashes().includes('ripemd160'));
|
||||
</code></pre>
|
||||
</li>
|
||||
<li>
|
||||
<p>Start with a 33-byte ECDSA secp256k1 public key, or a 32-byte Ed25119 public key. For Ed25519 keys, prefix the key with the byte <code>0xED</code>.</p>
|
||||
<pre><code>const pubkey_hex =
|
||||
'ED9434799226374926EDA3B54B1B461B4ABF7237962EAE18528FEA67595397FA32';
|
||||
const pubkey = Buffer.from(pubkey_hex, 'hex');
|
||||
assert(pubkey.length == 33);
|
||||
</code></pre>
|
||||
</li>
|
||||
<li>
|
||||
<p>Calculate the <a href="https://en.wikipedia.org/wiki/RIPEMD">RIPEMD160</a> hash of the SHA-256 hash of the public key. This value is the "Account ID".</p>
|
||||
<pre><code>const pubkey_inner_hash = crypto.createHash('sha256').update(pubkey);
|
||||
const pubkey_outer_hash = crypto.createHash('ripemd160');
|
||||
pubkey_outer_hash.update(pubkey_inner_hash.digest());
|
||||
const account_id = pubkey_outer_hash.digest();
|
||||
</code></pre>
|
||||
</li>
|
||||
<li>
|
||||
<p>Calculate the SHA-256 hash of the SHA-256 hash of the Account ID; take the first 4 bytes. This value is the "checksum".</p>
|
||||
<pre><code>const address_type_prefix = Buffer.from([0x00]);
|
||||
const payload = Buffer.concat([address_type_prefix, account_id]);
|
||||
const chksum_hash1 = crypto.createHash('sha256').update(payload).digest();
|
||||
const chksum_hash2 = crypto.createHash('sha256').update(chksum_hash1).digest();
|
||||
const checksum = chksum_hash2.slice(0,4);
|
||||
</code></pre>
|
||||
</li>
|
||||
<li>
|
||||
<p>Concatenate the payload and the checksum. Calculate the base58 value of the concatenated buffer. The result is the address.</p>
|
||||
<pre><code>const dataToEncode = Buffer.concat([payload, checksum]);
|
||||
const address = base58.encode(dataToEncode);
|
||||
console.log(address);
|
||||
// rDTXLQ7ZKZVKz33zJbHjgVShjsBnqMBhmN
|
||||
</code></pre>
|
||||
</li>
|
||||
</ol>
|
||||
<!-- -->
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<footer class="content-info" role="contentinfo">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-sm-12 absolute_bottom_footer">
|
||||
<div class="col-sm-8">
|
||||
<span>© 2013 - 2017 Ripple Labs, Inc. All Rights Reserved.</span>
|
||||
<span><a href="/terms-of-use/">Terms</a></span>
|
||||
<span><a href="/privacy-policy/">Privacy</a></span>
|
||||
</div>
|
||||
</div><!-- /.absolute_bottom_footer -->
|
||||
|
||||
</div><!-- /.row -->
|
||||
</div><!-- /.container -->
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,687 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<meta name="viewport" content="width=device-width">
|
||||
|
||||
<title>Amendments - Ripple Developer Portal</title>
|
||||
|
||||
<!-- favicon -->
|
||||
<link rel="icon" href="favicon.ico" type="image/x-icon">
|
||||
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon">
|
||||
|
||||
<!-- jQuery -->
|
||||
<script src="assets/vendor/jquery-1.11.1.min.js"></script>
|
||||
|
||||
<!-- Custom Stylesheets. ripple.css includes bootstrap, font stuff -->
|
||||
<link href="assets/css/ripple.css" rel="stylesheet" />
|
||||
<link href="assets/css/devportal.css" rel="stylesheet" />
|
||||
|
||||
<!-- Bootstrap JS -->
|
||||
<script src="assets/vendor/bootstrap.min.js"></script>
|
||||
|
||||
|
||||
<!-- syntax highlighting -->
|
||||
<link rel="stylesheet" href="assets/vendor/docco.min.css" />
|
||||
<script src="assets/vendor/highlight.min.js"></script>
|
||||
|
||||
<!-- syntax selection js -->
|
||||
<script src="assets/js/multicodetab.js"></script>
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
$(".multicode").minitabs();
|
||||
hljs.initHighlighting();
|
||||
make_code_expandable();
|
||||
});
|
||||
</script>
|
||||
|
||||
<script src="assets/js/expandcode.js"></script>
|
||||
<script src="assets/js/fixsidebarscroll.js"></script>
|
||||
|
||||
<!-- fontawesome icons -->
|
||||
<link rel="stylesheet" href="assets/vendor/fontawesome/css/font-awesome.min.css" />
|
||||
|
||||
</head>
|
||||
|
||||
<body class="page page-template page-template-template-dev-portal page-template-template-dev-portal-php sidebar-primary wpb-js-composer js-comp-ver-3.6.2 vc_responsive">
|
||||
<header role="banner" class="banner navbar navbar-default navbar-fixed-top initial_header">
|
||||
<div class="container">
|
||||
<div class="navbar-header">
|
||||
<a href="index.html" class="navbar-brand"><img src="assets/img/ripple-logo-color.png" class="logo"></a>
|
||||
</div><!-- /.navbar-header -->
|
||||
<div class="nav">
|
||||
<div class="draft-warning">DRAFT PAGE</div>
|
||||
</div><!-- /.nav -->
|
||||
|
||||
</div><!-- /.container -->
|
||||
|
||||
<div class="subnav dev_nav">
|
||||
<div class="container">
|
||||
<ul id="menu-dev-menu" class="menu">
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">References <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="reference-rippleapi.html">RippleAPI</a></li>
|
||||
<li><a href="reference-rippled.html">rippled</a></li>
|
||||
<li><a href="reference-transaction-format.html">Transaction Format</a></li>
|
||||
<li><a href="reference-ledger-format.html">Ledger Format</a></li>
|
||||
<li><a href="reference-data-api.html">Ripple Data API v2</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorials <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="tutorial-multisign.html">How to Multi-Sign</a></li>
|
||||
<li><a href="tutorial-paychan.html">Payment Channels Tutorial</a></li>
|
||||
<li><a href="concept-issuing-and-operational-addresses.html">Issuing and Operational Addresses</a></li>
|
||||
<li><a href="tutorial-reliable-transaction-submission.html">Reliable Transaction Submission</a></li>
|
||||
<li><a href="tutorial-rippleapi-beginners-guide.html">RippleAPI Beginners Guide</a></li>
|
||||
<li><a href="tutorial-rippled-setup.html">rippled Setup</a></li>
|
||||
<li><a href="tutorial-gateway-guide.html">Gateway Guide</a></li>
|
||||
<li><a href="tutorial-listing-xrp.html">Listing XRP as an Exchange</a></li>
|
||||
<li><a href="tutorial-escrow.html">Escrow Tutorials</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Features <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="concept-accounts.html">Accounts</a></li>
|
||||
<li><a href="concept-amendments.html">Amendments</a></li>
|
||||
<li><a href="concept-consensus.html">Consensus Process</a></li>
|
||||
<li><a href="concept-reaching-consensus.html">Reaching Consensus in the XRP Ledger</a></li>
|
||||
<li><a href="concept-fee-voting.html">Fee Voting</a></li>
|
||||
<li><a href="concept-fees.html">Fees (Disambiguation)</a></li>
|
||||
<li><a href="concept-freeze.html">Freeze</a></li>
|
||||
<li><a href="concept-partial-payments.html">Partial Payments</a></li>
|
||||
<li><a href="concept-paths.html">Paths</a></li>
|
||||
<li><a href="concept-reserves.html">Reserves</a></li>
|
||||
<li><a href="concept-stand-alone-mode.html">Stand-Alone Mode</a></li>
|
||||
<li><a href="concept-transaction-cost.html">Transaction Cost</a></li>
|
||||
<li><a href="concept-transfer-fees.html">Transfer Fees</a></li>
|
||||
<li><a href="concept-noripple.html">Understanding the NoRipple flag</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Gateway Bulletins <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="gb-2015-06.html">GB-2015-06: Corrections to Autobridging</a></li>
|
||||
<li><a href="gb-2015-05.html">GB-2015-05: Historical Ledger Query Migration</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">API Tools <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="ripple-api-tool.html">WebSocket API Tool</a></li>
|
||||
<li><a href="data-api-v2-tool.html">Data API v2 Tool</a></li>
|
||||
<li><a href="tool-jsonrpc.html">rippled JSON-RPC Tool</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li><a href="https://github.com/ripple/ripple-dev-portal" title="GitHub">Site Source</a></li>
|
||||
</ul><!-- /#dev-menu -->
|
||||
</div><!-- /.subnav .container -->
|
||||
</div><!-- /.subnav -->
|
||||
</header>
|
||||
|
||||
|
||||
<div class="wrap container" role="document">
|
||||
<aside class="sidebar" role="complementary">
|
||||
<div class="dev_nav_wrapper">
|
||||
<div id="cont">
|
||||
<h5>In this category:</h5>
|
||||
<ul class="dev_nav_sidebar">
|
||||
<li class="level-1"><a href="index.html">Category: Features</a></li>
|
||||
<li class="level-2"><a href="concept-accounts.html">Accounts</a></li>
|
||||
<li class="level-2"><a href="concept-amendments.html">Amendments</a></li>
|
||||
<li class="level-2"><a href="concept-consensus.html">Consensus Process</a></li>
|
||||
<li class="level-2"><a href="concept-reaching-consensus.html">Reaching Consensus in the XRP Ledger</a></li>
|
||||
<li class="level-2"><a href="concept-fee-voting.html">Fee Voting</a></li>
|
||||
<li class="level-2"><a href="concept-fees.html">Fees (Disambiguation)</a></li>
|
||||
<li class="level-2"><a href="concept-freeze.html">Freeze</a></li>
|
||||
<li class="level-2"><a href="concept-partial-payments.html">Partial Payments</a></li>
|
||||
<li class="level-2"><a href="concept-paths.html">Paths</a></li>
|
||||
<li class="level-2"><a href="concept-reserves.html">Reserves</a></li>
|
||||
<li class="level-2"><a href="concept-stand-alone-mode.html">Stand-Alone Mode</a></li>
|
||||
<li class="level-2"><a href="concept-transaction-cost.html">Transaction Cost</a></li>
|
||||
<li class="level-2"><a href="concept-transfer-fees.html">Transfer Fees</a></li>
|
||||
<li class="level-2"><a href="concept-noripple.html">Understanding the NoRipple flag</a></li>
|
||||
</ul>
|
||||
<hr />
|
||||
<h5>In this page:</h5>
|
||||
<ul class="dev_nav_sidebar" id="dactyl_toc_sidebar">
|
||||
<li class="level-1"><a href="#amendments">Amendments</a></li>
|
||||
<li class="level-2"><a href="#background">Background</a></li>
|
||||
<li class="level-2"><a href="#about-amendments">About Amendments</a></li>
|
||||
<li class="level-2"><a href="#amendment-process">Amendment Process</a></li>
|
||||
<li class="level-2"><a href="#amendment-voting">Amendment Voting</a></li>
|
||||
<li class="level-3"><a href="#configuring-amendment-voting">Configuring Amendment Voting</a></li>
|
||||
<li class="level-3"><a href="#amendment-blocked">Amendment Blocked</a></li>
|
||||
<li class="level-2"><a href="#testing-amendments">Testing Amendments</a></li>
|
||||
<li class="level-1"><a href="#known-amendments">Known Amendments</a></li>
|
||||
<li class="level-2"><a href="#cryptoconditions">CryptoConditions</a></li>
|
||||
<li class="level-2"><a href="#enforceinvariants">EnforceInvariants</a></li>
|
||||
<li class="level-2"><a href="#escrow">Escrow</a></li>
|
||||
<li class="level-2"><a href="#feeescalation">FeeEscalation</a></li>
|
||||
<li class="level-2"><a href="#fix1368">fix1368</a></li>
|
||||
<li class="level-2"><a href="#fix1373">fix1373</a></li>
|
||||
<li class="level-2"><a href="#flow">Flow</a></li>
|
||||
<li class="level-2"><a href="#flowcross">FlowCross</a></li>
|
||||
<li class="level-2"><a href="#flowv2">FlowV2</a></li>
|
||||
<li class="level-2"><a href="#multisign">MultiSign</a></li>
|
||||
<li class="level-2"><a href="#ownerpaysfee">OwnerPaysFee</a></li>
|
||||
<li class="level-2"><a href="#paychan">PayChan</a></li>
|
||||
<li class="level-2"><a href="#shamapv2">SHAMapV2</a></li>
|
||||
<li class="level-2"><a href="#suspay">SusPay</a></li>
|
||||
<li class="level-2"><a href="#trustsetauth">TrustSetAuth</a></li>
|
||||
<li class="level-2"><a href="#ticksize">TickSize</a></li>
|
||||
<li class="level-2"><a href="#tickets">Tickets</a></li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
<main class="main" role="main">
|
||||
<div class='content'>
|
||||
<h1 id="amendments">Amendments</h1>
|
||||
<p><a href="https://github.com/ripple/rippled/releases/tag/0.31.0" title="Introduced in: rippled 0.31.0"><img alt="Introduced in: rippled 0.31.0" class="dactyl_badge" src="https://img.shields.io/badge/Introduced%20in-rippled%200.31.0-blue.svg"/></a></p>
|
||||
<p>The Amendments system provides a means of introducing new features to the decentralized XRP Ledger network without causing disruptions. The amendments system works by utilizing the core consensus process of the network to approve any changes by showing continuous support before those changes go into effect. An amendment normally requires <strong>80% support for two weeks</strong> before it can apply.</p>
|
||||
<p>When an Amendment has been enabled, it applies permanently to all ledger versions after the one that included it. You cannot disable an Amendment, unless you introduce a new Amendment to do so.</p>
|
||||
<h2 id="background">Background</h2>
|
||||
<p>Any changes to transaction processing could cause servers to build a different ledger with the same set of transactions. If some <em>validators</em> (<code>rippled</code> servers <a href="tutorial-rippled-setup.html#reasons-to-run-a-validator">participating in consensus</a>) have upgraded to a new version of the software while other validators use the old version, this could cause anything from minor inconveniences to full outages. In the minor case, a minority of servers spend more time and bandwidth fetching the actual consensus ledger because they cannot build it using the transaction processing rules they already know. In the worst case, <a href="https://ripple.com/build/ripple-ledger-consensus-process/">the consensus process</a> might be unable to validate new ledger versions because servers with different rules could not reach a consensus on the exact ledger to build.</p>
|
||||
<p>Amendments solve this problem, so that new features can be enabled only when enough validators support those features.</p>
|
||||
<p>Users and businesses who rely on the XRP Ledger can also use Amendments to provide advance notice of changes in transaction processing that might affect their business. However, API changes that do not impact transaction processing or <a href="https://ripple.com/build/ripple-ledger-consensus-process/">the consensus process</a> do not need Amendments.</p>
|
||||
<h2 id="about-amendments">About Amendments</h2>
|
||||
<p>An amendment is a fully-functional feature or change, waiting to be enabled by the peer-to-peer network as a part of the consensus process. A <code>rippled</code> server that wants to use an amendment has code for two modes: without the amendment (old behavior) and with the amendment (new behavior).</p>
|
||||
<p>Every amendment has a unique identifying hex value and a short name. The short name is for human use, and is not used in the amendment process. Two servers can support the same amendment ID while using different names to describe it. An amendment's name is not guaranteed to be unique.</p>
|
||||
<p>By convention, Ripple's developers use the SHA-512Half hash of the amendment name as the amendment ID.</p>
|
||||
<p>See also: <a href="#known-amendments">Known Amendments</a></p>
|
||||
<h2 id="amendment-process">Amendment Process</h2>
|
||||
<p>Every 256th ledger is called a "flag" ledger. The process of approving an amendment starts in the ledger version immediately before the flag ledger. When <code>rippled</code> validator servers send validation messages for that ledger, those servers also submit votes in favor of specific amendments. If a validator does not vote in favor of an amendment, that is the same as voting against the amendment. (<a href="concept-fee-voting.html">Fee Voting</a> also occurs around flag ledgers.)</p>
|
||||
<p>The flag ledger itself has no special contents. However, during that time, the servers look at the votes of the validators they trust, and decide whether to insert an <a href="reference-transaction-format.html#enableamendment"><code>EnableAmendment</code> pseudo-transaction</a> into the following ledger. The flags of an EnableAmendment pseudo-transaction show what the server thinks happened:</p>
|
||||
<ul>
|
||||
<li>The <code>tfGotMajority</code> flag means that support for the amendment has increased to at least 80% of trusted validators.</li>
|
||||
<li>The <code>tfLostMajority</code> flag means that support for the amendment has decreased to less than 80% of trusted validators.</li>
|
||||
<li>An EnableAmendment pseudo-transaction with no flags means that support for the amendment has been enabled. (The change in transaction processing applies to every ledger after this one.)</li>
|
||||
</ul>
|
||||
<p>A server only inserts the pseudo-transaction to enable an amendment if all of the following conditions are met:</p>
|
||||
<ul>
|
||||
<li>The amendment has not already been enabled.</li>
|
||||
<li>A previous ledger includes an EnableAmendment pseudo-transaction for this amendment with the <code>tfGotMajority</code> flag enabled.</li>
|
||||
<li>The previous ledger in question is an ancestor of the current ledger.</li>
|
||||
<li>The previous ledger in question has a close time that is at least <strong>two weeks</strong> before the close time of the latest flag ledger.</li>
|
||||
<li>There are no EnableAmendment pseudo-transactions for this amendment with the <code>tfLostMajority</code> flag enabled in the consensus ledgers between the <code>tfGotMajority</code> pseudo-transaction and the current ledger.</li>
|
||||
</ul>
|
||||
<p>Theoretically, a <code>tfLostMajority</code> EnableAmendment pseudo-transaction could be included in the same ledger as the pseudo-transaction to enable an amendment. In this case, the pseudo-transaction with the <code>tfLostMajority</code> pseudo-transaction has no effect.</p>
|
||||
<h2 id="amendment-voting">Amendment Voting</h2>
|
||||
<p>Each version of <code>rippled</code> is compiled with a list of known amendments and the code to implement those amendments. By default, <code>rippled</code> supports known amendments and opposes unknown amendments. Operators of <code>rippled</code> validators can <a href="#configuring-amendment-voting">configure their servers</a> to explicitly support or oppose certain amendments, even if those amendments are not known to their <code>rippled</code> versions.</p>
|
||||
<p>To become enabled, an amendment must be supported by at least 80% of trusted validators continuously for two weeks. If support for an amendment goes below 80% of trusted validators, the amendment is temporarily rejected. The two week period starts over if the amendment regains support of at least 80% of trusted validators. (This can occur if validators vote differently, or if there is a change in which validators are trusted.) An amendment can gain and lose a majority an unlimited number of times before it becomes permanently enabled. An amendment cannot be permanently rejected, but it becomes very unlikely for an amendment to become enabled if new versions of <code>rippled</code> do not have the amendment in their known amendments list.</p>
|
||||
<p>As with all aspects of the consensus process, amendment votes are only taken into account by servers that trust the validators sending those votes. At this time, Ripple (the company) recommends only trusting the 5 default validators that Ripple operates. For now, trusting only those validators is enough to coordinate with Ripple on releasing new features.</p>
|
||||
<h3 id="configuring-amendment-voting">Configuring Amendment Voting</h3>
|
||||
<p>You can temporarily configure an amendment using the <a href="reference-rippled.html#feature"><code>feature</code> command</a>. To make a persistent change to your server's support for an amendment, change your server's <code>rippled.cfg</code> file.</p>
|
||||
<p>Use the <code>[veto_amendments]</code> stanza to list amendments you do not want the server to vote for. Each line should contain one amendment's unique ID, optionally followed by the short name for the amendment. For example:</p>
|
||||
<pre><code>[veto_amendments]
|
||||
C1B8D934087225F509BEB5A8EC24447854713EE447D277F69545ABFA0E0FD490 Tickets
|
||||
DA1BD556B42D85EA9C84066D028D355B52416734D3283F85E216EA5DA6DB7E13 SusPay
|
||||
</code></pre>
|
||||
<p>Use the <code>[amendments]</code> stanza to list amendments you want to vote for. (Even if you do not list them here, by default a server votes for all the amendments it knows how to apply.) Each line should contain one amendment's unique ID, optionally followed by the short name for the amendment. For example:</p>
|
||||
<pre><code>[amendments]
|
||||
4C97EBA926031A7CF7D7B36FDE3ED66DDA5421192D63DE53FFB46E43B9DC8373 MultiSign
|
||||
42426C4D4F1009EE67080A9B7965B44656D7714D104A72F9B4369F97ABF044EE FeeEscalation
|
||||
</code></pre>
|
||||
<h3 id="amendment-blocked">Amendment Blocked</h3>
|
||||
<p>When an amendment gets enabled for the network after the voting process, servers running earlier versions of <code>rippled</code> that do not know about the amendment become "amendment blocked" because they no longer understand the rules of the network. Servers that are amendment blocked:</p>
|
||||
<ul>
|
||||
<li>Cannot determine the validity of a ledger</li>
|
||||
<li>Cannot submit or process transactions</li>
|
||||
<li>Do not participate in the consensus process</li>
|
||||
<li>Do not vote on future amendments</li>
|
||||
</ul>
|
||||
<p>Becoming amendment blocked is a security feature to protect backend applications. Rather than guessing and maybe misinterpreting a ledger after new rules have applied, <code>rippled</code> reports that it does not know the state of the ledger because it does not know how the amendment works.</p>
|
||||
<p>The amendments that a <code>rippled</code> server is configured to vote for or against have no impact on whether the server becomes amendment blocked. A <code>rippled</code> server always follows the set of amendments enabled by the rest of the network, to the extent possible. A server only becomes amendment blocked if the enabled amendment is not included in the amendment definitions compiled into the server's source code -- in other words, if the amendment is newer than the server.</p>
|
||||
<p>If your server is amendment blocked, you must <a href="tutorial-rippled-setup.html#updating-rippled">upgrade to a new version</a> to sync with the network.</p>
|
||||
<h2 id="testing-amendments">Testing Amendments</h2>
|
||||
<p>If you want to see how <code>rippled</code> behaves with an amendment enabled, before that amendment gets enabled on the production network, you can run use <code>rippled</code>'s configuration file to forcibly enable a feature. This is intended for development purposes only.</p>
|
||||
<p>Because other members of the consensus network probably do not have the feature enabled, you should not use this feature while connecting to the production network. While testing with features forcibly enabled, you should run <code>rippled</code> in <a href="concept-stand-alone-mode.html">Stand-Alone Mode</a>.</p>
|
||||
<p>To forcibly enable a feature, add a <code>[features]</code> stanza to your <code>rippled.cfg</code> file. In this stanza, add the short names of the features to enable, one per line. For example:</p>
|
||||
<pre><code>[features]
|
||||
MultiSign
|
||||
TrustSetAuth
|
||||
</code></pre>
|
||||
<h1 id="known-amendments">Known Amendments</h1>
|
||||
<p><a href="https://github.com/ripple/rippled/blob/release/src/ripple/app/main/Amendments.cpp" title="Source">[Source]<br/></a></p>
|
||||
<p>The following is a comprehensive list of all known amendments and their status on the production XRP Ledger:</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th align="left">Name</th>
|
||||
<th align="left">Introduced</th>
|
||||
<th align="left">Status</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td align="left"><a href="#flowcross">FlowCross</a></td>
|
||||
<td align="left">v0.70.0</td>
|
||||
<td align="left"><a title="Planned: TBD"><img alt="Planned: TBD" class="dactyl_badge" src="https://img.shields.io/badge/Planned-TBD-lightgrey.svg"/></a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left"><a href="#shamapv2">SHAMapV2</a></td>
|
||||
<td align="left">v0.33.0</td>
|
||||
<td align="left"><a title="Planned: TBD"><img alt="Planned: TBD" class="dactyl_badge" src="https://img.shields.io/badge/Planned-TBD-lightgrey.svg"/></a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left"><a href="#ownerpaysfee">OwnerPaysFee</a></td>
|
||||
<td align="left">v0.33.0</td>
|
||||
<td align="left"><a title="Planned: TBD"><img alt="Planned: TBD" class="dactyl_badge" src="https://img.shields.io/badge/Planned-TBD-lightgrey.svg"/></a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left"><a href="#tickets">Tickets</a></td>
|
||||
<td align="left">N/A</td>
|
||||
<td align="left"><a title="Planned: TBD"><img alt="Planned: TBD" class="dactyl_badge" src="https://img.shields.io/badge/Planned-TBD-lightgrey.svg"/></a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left"><a href="#enforceinvariants">EnforceInvariants</a></td>
|
||||
<td align="left">v0.70.0</td>
|
||||
<td align="left"><a href="https://xrpcharts.ripple.com/#/transactions/17593B03F7D3283966F3C0ACAF4984F26E9D884C9A202097DAED0523908E76C6" title="Enabled: 2017-07-07"><img alt="Enabled: 2017-07-07" class="dactyl_badge" src="https://img.shields.io/badge/Enabled-2017--07--07-green.svg"/></a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left"><a href="#fix1373">fix1373</a></td>
|
||||
<td align="left">v0.70.0</td>
|
||||
<td align="left"><a href="https://xrpcharts.ripple.com/#/transactions/7EBA3852D111EA19D03469F6870FAAEBF84C64F1B9BAC13B041DDD26E28CA399" title="Enabled: 2017-07-07"><img alt="Enabled: 2017-07-07" class="dactyl_badge" src="https://img.shields.io/badge/Enabled-2017--07--07-green.svg"/></a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left"><a href="#fix1368">fix1368</a></td>
|
||||
<td align="left">v0.60.0</td>
|
||||
<td align="left"><a href="https://xrpcharts.ripple.com/#/transactions/3D20DE5CD19D5966865A7D0405FAC7902A6F623659667D6CB872DF7A94B6EF3F" title="Enabled: 2017-03-31"><img alt="Enabled: 2017-03-31" class="dactyl_badge" src="https://img.shields.io/badge/Enabled-2017--03--31-green.svg"/></a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left"><a href="#paychan">PayChan</a></td>
|
||||
<td align="left">v0.33.0</td>
|
||||
<td align="left"><a href="https://xrpcharts.ripple.com/#/transactions/16135C0B4AB2419B89D4FB4569B8C37FF76B9EF9CE0DD99CCACB5734445AFD7E" title="Enabled: 2017-03-31"><img alt="Enabled: 2017-03-31" class="dactyl_badge" src="https://img.shields.io/badge/Enabled-2017--03--31-green.svg"/></a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left"><a href="#escrow">Escrow</a></td>
|
||||
<td align="left">v0.60.0</td>
|
||||
<td align="left"><a href="https://xrpcharts.ripple.com/#/transactions/C581E0A3F3832FFFEEB13C497658F475566BD7695B0BBA531A774E6739801515" title="Enabled: 2017-03-31"><img alt="Enabled: 2017-03-31" class="dactyl_badge" src="https://img.shields.io/badge/Enabled-2017--03--31-green.svg"/></a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left"><a href="#ticksize">TickSize</a></td>
|
||||
<td align="left">v0.50.0</td>
|
||||
<td align="left"><a href="https://xrpcharts.ripple.com/#/transactions/A12430E470BE5C846759EAE3C442FF03374D5D73ECE5815CF4906894B769565E" title="Enabled: 2017-02-21"><img alt="Enabled: 2017-02-21" class="dactyl_badge" src="https://img.shields.io/badge/Enabled-2017--02--21-green.svg"/></a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left"><a href="#suspay">SusPay</a></td>
|
||||
<td align="left">v0.31.0</td>
|
||||
<td align="left"><a href="https://ripple.com/dev-blog/ticksize-amendment-open-voting/#upcoming-features" title="Vetoed: Removed in v0.60.0"><img alt="Vetoed: Removed in v0.60.0" class="dactyl_badge" src="https://img.shields.io/badge/Vetoed-Removed%20in%20v0.60.0-red.svg"/></a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left"><a href="#cryptoconditions">CryptoConditions</a></td>
|
||||
<td align="left">v0.50.0</td>
|
||||
<td align="left"><a href="https://xrpcharts.ripple.com/#/transactions/8EB00131E1C3DB35EDFF45C155D941E18C3E86BC1934FF987D2DA204F4065F15" title="Enabled: 2017-01-03"><img alt="Enabled: 2017-01-03" class="dactyl_badge" src="https://img.shields.io/badge/Enabled-2017--01--03-green.svg"/></a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left"><a href="#flow">Flow</a></td>
|
||||
<td align="left">v0.33.0</td>
|
||||
<td align="left"><a href="https://xrpcharts.ripple.com/#/transactions/C06CE3CABA3907389E4DD296C5F31C73B1548CC20BD7B83416C78CD7D4CD38FC" title="Enabled: 2016-10-21"><img alt="Enabled: 2016-10-21" class="dactyl_badge" src="https://img.shields.io/badge/Enabled-2016--10--21-green.svg"/></a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left"><a href="#flowv2">FlowV2</a></td>
|
||||
<td align="left">v0.32.1</td>
|
||||
<td align="left"><a href="https://ripple.com/dev-blog/flowv2-amendment-vetoed/" title="Vetoed: Removed in v0.33.0"><img alt="Vetoed: Removed in v0.33.0" class="dactyl_badge" src="https://img.shields.io/badge/Vetoed-Removed%20in%20v0.33.0-red.svg"/></a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left"><a href="#trustsetauth">TrustSetAuth</a></td>
|
||||
<td align="left">v0.30.0</td>
|
||||
<td align="left"><a href="https://xrpcharts.ripple.com/#/transactions/0E589DE43C38AED63B64FF3DA87D349A038F1821212D370E403EB304C76D70DF" title="Enabled: 2016-07-19"><img alt="Enabled: 2016-07-19" class="dactyl_badge" src="https://img.shields.io/badge/Enabled-2016--07--19-green.svg"/></a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left"><a href="#multisign">MultiSign</a></td>
|
||||
<td align="left">v0.31.0</td>
|
||||
<td align="left"><a href="https://xrpcharts.ripple.com/#/transactions/168F8B15F643395E59B9977FC99D6310E8708111C85659A9BAF8B9222EEAC5A7" title="Enabled: 2016-06-27"><img alt="Enabled: 2016-06-27" class="dactyl_badge" src="https://img.shields.io/badge/Enabled-2016--06--27-green.svg"/></a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left"><a href="#feeescalation">FeeEscalation</a></td>
|
||||
<td align="left">v0.31.0</td>
|
||||
<td align="left"><a href="https://xrpcharts.ripple.com/#/transactions/5B1F1E8E791A9C243DD728680F108FEF1F28F21BA3B202B8F66E7833CA71D3C3" title="Enabled: 2016-05-19"><img alt="Enabled: 2016-05-19" class="dactyl_badge" src="https://img.shields.io/badge/Enabled-2016--05--19-green.svg"/></a></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p class="devportal-callout note"><strong>Note:</strong> In many cases, an incomplete version of the code for an amendment is present in previous versions of the software. The "Introduced" version in the table above is the first stable version.</p>
|
||||
<h2 id="cryptoconditions">CryptoConditions</h2>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th align="left">Amendment ID</th>
|
||||
<th align="left">Status</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td align="left">1562511F573A19AE9BD103B5D6B9E01B3B46805AEC5D3C4805C902B514399146</td>
|
||||
<td align="left">Enabled</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>Although this amendment is enabled, it has no effect unless the <a href="#suspay">SusPay</a> amendment is also enabled. Ripple does not expect SusPay to become enabled. Instead, Ripple plans to incorporate crypto-conditions in the <a href="#escrow">Escrow</a> amendment.</p>
|
||||
<h2 id="enforceinvariants">EnforceInvariants</h2>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th align="left">Amendment ID</th>
|
||||
<th align="left">Status</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td align="left">DC9CA96AEA1DCF83E527D1AFC916EFAF5D27388ECA4060A88817C1238CAEE0BF</td>
|
||||
<td align="left">Enabled</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>Adds sanity checks to transaction processing to ensure that certain conditions are always met. This provides an extra, independent layer of protection against bugs in transaction processing that could otherwise cause exploits and vulnerabilities in the XRP Ledger. Ripple expects to add more invariant checks in future versions of <code>rippled</code> without additional amendments.</p>
|
||||
<p>Introduces two new transaction error codes, <code>tecINVARIANT_FAILED</code> and <code>tefINVARIANT_FAILED</code>. Changes transaction processing to add the new checks.</p>
|
||||
<p>Examples of invariant checks:</p>
|
||||
<ul>
|
||||
<li>The total amount of XRP destroyed by a transaction must match the <a href="concept-transaction-cost.html">transaction cost</a> exactly.</li>
|
||||
<li>XRP cannot be created.</li>
|
||||
<li><a href="reference-ledger-format.html#accountroot"><code>AccountRoot</code> objects in the ledger</a> cannot be deleted. (See also: <a href="concept-accounts.html#permanence-of-accounts">Permanence of Accounts</a>.)</li>
|
||||
<li><a href="reference-ledger-format.html#ledger-node-types">An object in the ledger</a> cannot change its type. (The <code>LedgerEntryType</code> field is immutable.)</li>
|
||||
<li>There cannot be a trust line for XRP.</li>
|
||||
</ul>
|
||||
<h2 id="escrow">Escrow</h2>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th align="left">Amendment ID</th>
|
||||
<th align="left">Status</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td align="left">07D43DCE529B15A10827E5E04943B496762F9A88E3268269D69C44BE49E21104</td>
|
||||
<td align="left">Enabled</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>Replaces the <a href="#suspay">SusPay</a> and <a href="#cryptoconditions">CryptoConditions</a> amendments.</p>
|
||||
<p>Provides "suspended payments" for XRP for escrow within the XRP Ledger, including support for <a href="https://tools.ietf.org/html/draft-thomas-crypto-conditions-02">Interledger Protocol Crypto-Conditions</a>. Creates a new ledger node type for suspended payments and new transaction types to create, execute, and cancel suspended payments.</p>
|
||||
<h2 id="feeescalation">FeeEscalation</h2>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th align="left">Amendment ID</th>
|
||||
<th align="left">Status</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td align="left">42426C4D4F1009EE67080A9B7965B44656D7714D104A72F9B4369F97ABF044EE</td>
|
||||
<td align="left">Enabled</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>Changes the way the <a href="concept-transaction-cost.html">transaction cost</a> applies to proposed transactions. Modifies the consensus process to prioritize transactions that pay a higher transaction cost. <!-- STYLE_OVERRIDE: prioritize --></p>
|
||||
<p>This amendment introduces a fixed-size transaction queue for transactions that were not able to be included in the previous consensus round. If the <code>rippled</code> servers in the consensus network are under heavy load, they queue the transactions with the lowest transaction cost for later ledgers. Each consensus round prioritizes transactions from the queue with the largest transaction cost (<code>Fee</code> value), and includes as many transactions as the consensus network can process. If the transaction queue is full, transactions drop from the queue entirely, starting with the ones that have the lowest transaction cost.</p>
|
||||
<p>While the consensus network is under heavy load, legitimate users can pay a higher transaction cost to make sure their transactions get processed. The situation persists until the entire backlog of cheap transactions is processed or discarded.</p>
|
||||
<p>A transaction remains in the queue until one of the following happens:</p>
|
||||
<ul>
|
||||
<li>It gets applied to a validated ledger (regardless of success or failure)</li>
|
||||
<li>It becomes invalid (for example, the <a href="reference-transaction-format.html#lastledgersequence"><code>LastLedgerSequence</code></a> causes it to expire)</li>
|
||||
<li>It gets dropped because there are too many transactions in the queue with a higher transaction cost.</li>
|
||||
</ul>
|
||||
<h2 id="fix1368">fix1368</h2>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th align="left">Amendment ID</th>
|
||||
<th align="left">Status</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td align="left">E2E6F2866106419B88C50045ACE96368558C345566AC8F2BDF5A5B5587F0E6FA</td>
|
||||
<td align="left">Enabled</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>Fixes a minor bug in transaction processing that causes some payments to fail when they should be valid. Specifically, during payment processing, some payment steps that are expected to produce a certain amount of currency may produce a microscopically different amount, due to a loss of precision related to floating-point number representation. When this occurs, those payments fail because they cannot deliver the exact amount intended. The fix1368 amendment corrects transaction processing so payments can no longer fail in this manner.</p>
|
||||
<h2 id="fix1373">fix1373</h2>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th align="left">Amendment ID</th>
|
||||
<th align="left">Status</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td align="left">42EEA5E28A97824821D4EF97081FE36A54E9593C6E4F20CBAE098C69D2E072DC</td>
|
||||
<td align="left">Enabled</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>Fixes a minor bug in transaction processing that causes failures when trying to prepare certain <a href="concept-paths.html">payment paths</a> for processing. As a result, payments could not use certain paths that should have been valid but were invalidly prepared. Without this amendment, those payments are forced to use less-preferable paths or may even fail.</p>
|
||||
<p>The fix1373 amendment corrects the issue so that the paths are properly prepared and payments can use them. It also disables some inappropriate paths that are currently allowed, including paths whose <a href="concept-paths.html#path-specifications">steps</a> include conflicting fields and paths that loop through the same object more than once.</p>
|
||||
<h2 id="flow">Flow</h2>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th align="left">Amendment ID</th>
|
||||
<th align="left">Status</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td align="left">740352F2412A9909880C23A559FCECEDA3BE2126FED62FC7660D628A06927F11</td>
|
||||
<td align="left">Enabled</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>Replaces the payment processing engine with a more robust and efficient rewrite called the Flow engine. The new version of the payment processing engine is intended to follow the same rules as the old one, but occasionally produces different results due to floating point rounding. This Amendment supersedes the <a href="https://ripple.com/dev-blog/flowv2-amendment-vetoed/">FlowV2</a> amendment.</p>
|
||||
<p>The Flow Engine also makes it easier to improve and expand the payment engine with further Amendments.</p>
|
||||
<h2 id="flowcross">FlowCross</h2>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th align="left">Amendment ID</th>
|
||||
<th align="left">Status</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td align="left">3012E8230864E95A58C60FD61430D7E1B4D3353195F2981DC12B0C7C0950FFAC</td>
|
||||
<td align="left">Released but not enabled</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>Streamlines the offer crossing logic in the XRP Ledger's decentralized exchange. Uses the updated code from the <a href="#flow">Flow</a> amendment to power offer crossing, so <a href="reference-transaction-format.html#offercreate">OfferCreate transactions</a> and <a href="reference-transaction-format.html#payment">Payment transactions</a> share more code. This has subtle differences in how offers are processed:</p>
|
||||
<ul>
|
||||
<li>Rounding is slightly different in some cases.</li>
|
||||
<li>Due to differences in rounding, some combinations of offers may be ranked higher or lower than by the old logic, and taken preferentially.</li>
|
||||
<li>The new logic may delete more or fewer offers than the old logic. (This includes cases caused by differences in rounding and offers that were incorrectly removed as unfunded by the old logic.)</li>
|
||||
</ul>
|
||||
<h2 id="flowv2">FlowV2</h2>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th align="left">Amendment ID</th>
|
||||
<th align="left">Status</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td align="left">5CC22CFF2864B020BD79E0E1F048F63EF3594F95E650E43B3F837EF1DF5F4B26</td>
|
||||
<td align="left">Withdrawn</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>This is a previous version of the <a href="#flow">Flow</a> amendment. It was <a href="https://ripple.com/dev-blog/flowv2-amendment-vetoed/">rejected due to a bug</a> and removed in version 0.33.0.</p>
|
||||
<h2 id="multisign">MultiSign</h2>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th align="left">Amendment ID</th>
|
||||
<th align="left">Status</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td align="left">4C97EBA926031A7CF7D7B36FDE3ED66DDA5421192D63DE53FFB46E43B9DC8373</td>
|
||||
<td align="left">Enabled</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>Introduces <a href="reference-transaction-format.html#multi-signing">multi-signing</a> as a way to authorize transactions. Creates the <a href="reference-ledger-format.html#signerlist"><code>SignerList</code> ledger node type</a> and the <a href="reference-transaction-format.html#signerlistset"><code>SignerListSet</code> transaction type</a>. Adds the optional <code>Signers</code> field to all transaction types. Modifies some transaction result codes.</p>
|
||||
<p>This amendment allows addresses to have a list of signers who can authorize transactions from that address in a multi-signature. The list has a quorum and 1 to 8 weighted signers. This allows various configurations, such as "any 3-of-5" or "signature from A plus any other two signatures."</p>
|
||||
<p>Signers can be funded or unfunded addresses. Funded addresses in a signer list can sign using a regular key (if defined) or master key (unless disabled). Unfunded addresses can sign with a master key. Multi-signed transactions have the same permissions as transactions signed with a regular key.</p>
|
||||
<p>An address with a SignerList can disable the master key even if a regular key is not defined. An address with a SignerList can also remove a regular key even if the master key is disabled. The <code>tecMASTER_DISABLED</code> transaction result code is renamed <code>tecNO_ALTERNATIVE_KEY</code>. The <code>tecNO_REGULAR_KEY</code> transaction result is retired and replaced with <code>tecNO_ALTERNATIVE_KEY</code>. Additionally, this amendment adds the following new <a href="reference-transaction-format.html#result-categories">transaction result codes</a>:</p>
|
||||
<ul>
|
||||
<li><code>temBAD_SIGNER</code></li>
|
||||
<li><code>temBAD_QUORUM</code></li>
|
||||
<li><code>temBAD_WEIGHT</code></li>
|
||||
<li><code>tefBAD_SIGNATURE</code></li>
|
||||
<li><code>tefBAD_QUORUM</code></li>
|
||||
<li><code>tefNOT_MULTI_SIGNING</code></li>
|
||||
<li><code>tefBAD_AUTH_MASTER</code></li>
|
||||
</ul>
|
||||
<h2 id="ownerpaysfee">OwnerPaysFee</h2>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th align="left">Amendment ID</th>
|
||||
<th align="left">Status</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td align="left">9178256A980A86CF3D70D0260A7DA6402AAFE43632FDBCB88037978404188871</td>
|
||||
<td align="left">Released but not enabled</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>Fixes an inconsistency in the way <a href="concept-transfer-fees.html">transfer fees</a> are calculated between <a href="reference-transaction-format.html#offercreate">OfferCreate</a> and <a href="reference-transaction-format.html#payment">Payment</a> transaction types. Without this amendment, the holder of the issuances pays the transfer fee if an offer is executed in offer placement, but the initial sender of a transaction pays the transfer fees for offers that are executed as part of payment processing. With this amendment, the holder of the issuances always pays the transfer fee, regardless of whether the offer is executed as part of a Payment or an OfferCreate transaction. Offer processing outside of payments is unaffected.</p>
|
||||
<p>This Amendment requires the <a href="#flow">Flow Amendment</a> to be enabled.</p>
|
||||
<h2 id="paychan">PayChan</h2>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th align="left">Amendment ID</th>
|
||||
<th align="left">Status</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td align="left">08DE7D96082187F6E6578530258C77FAABABE4C20474BDB82F04B021F1A68647</td>
|
||||
<td align="left">Enabled</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>Creates "Payment Channels" for XRP. Payment channels are a tool for facilitating repeated, unidirectional payments or temporary credit between two parties. Ripple expects this feature to be useful for the <a href="https://interledger.org/">Interledger Protocol</a>. One party creates a Payment Channel and sets aside some XRP in that channel for a predetermined expiration. Then, through off-ledger secure communications, the sender can send "Claim" messages to the receiver. The receiver can redeem the Claim messages before the expiration, or choose not to in case the payment is not needed. The receiver can verify Claims individually without actually distributing them to the network and waiting for the consensus process to redeem them, then redeem the batched content of many small Claims later, as long as it is within the expiration.</p>
|
||||
<p>Creates three new transaction types:<a href="reference-transaction-format.html#paymentchannelcreate">PaymentChannelCreate</a>, <a href="reference-transaction-format.html#paymentchannelclaim">PaymentChannelClaim</a>, and <a href="reference-transaction-format.html#paymentchannelfund">PaymentChannelFund</a>. Creates a new ledger node type, <a href="reference-ledger-format.html#paychannel">PayChannel</a>. Defines an off-ledger data structure called a <code>Claim</code>, used in the ChannelClaim transaction. Creates new <code>rippled</code> API methods: <a href="reference-rippled.html#channel-authorize"><code>channel_authorize</code></a> (creates a signed Claim), <a href="reference-rippled.html#channel-verify"><code>channel_verify</code></a> (verifies a signed Claim), and <a href="reference-rippled.html#account-channels"><code>account_channels</code></a> (lists Channels associated with an account).</p>
|
||||
<p>For more information, see the <a href="tutorial-paychan.html">Payment Channels Tutorial</a>.</p>
|
||||
<h2 id="shamapv2">SHAMapV2</h2>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th align="left">Amendment ID</th>
|
||||
<th align="left">Status</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td align="left">C6970A8B603D8778783B61C0D445C23D1633CCFAEF0D43E7DBCD1521D34BD7C3</td>
|
||||
<td align="left">Released but not enabled</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>Changes the hash tree structure that <code>rippled</code> uses to represent a ledger. The new structure is more compact and efficient than the previous version. This affects how ledger hashes are calculated, but has no other user-facing consequences.</p>
|
||||
<p>When this amendment is activated, the XRP Ledger will undergo a brief scheduled unavailability while the network calculates the changes to the hash tree structure.</p>
|
||||
<h2 id="suspay">SusPay</h2>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th align="left">Amendment ID</th>
|
||||
<th align="left">Status</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td align="left">DA1BD556B42D85EA9C84066D028D355B52416734D3283F85E216EA5DA6DB7E13</td>
|
||||
<td align="left">Enabled on TestNet; not intended for production.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>This amendment is currently enabled on the <a href="https://ripple.com/build/ripple-test-net/">Ripple Test Net</a>. In production, Ripple expects to enable similar functionality with the <a href="#escrow">Escrow</a> amendment instead.</p>
|
||||
<h2 id="trustsetauth">TrustSetAuth</h2>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th align="left">Amendment ID</th>
|
||||
<th align="left">Status</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td align="left">6781F8368C4771B83E8B821D88F580202BCB4228075297B19E4FDC5233F1EFDC</td>
|
||||
<td align="left">Enabled</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>Allows pre-authorization of accounting relationships (zero-balance trust lines) when using <a href="tutorial-gateway-guide.html#authorized-accounts">Authorized Accounts</a>.</p>
|
||||
<p>With this amendment enabled, a <code>TrustSet</code> transaction with <a href="reference-transaction-format.html#trustset-flags"><code>tfSetfAuth</code> enabled</a> can create a new <a href="reference-ledger-format.html#ripplestate"><code>RippleState</code> ledger node</a> even if it keeps all the other values of the <code>RippleState</code> node in their default state. The new <code>RippleState</code> node has the <a href="reference-ledger-format.html#ripplestate-flags"><code>lsfLowAuth</code> or <code>lsfHighAuth</code> flag</a> enabled, depending on whether the sender of the transaction is considered the low node or the high node. The sender of the transaction must have already enabled <a href="reference-ledger-format.html#accountroot-flags"><code>lsfRequireAuth</code></a> by sending an <a href="reference-transaction-format.html#accountset">AccountSet transaction</a> with the <a href="reference-transaction-format.html#accountset-flags">asfRequireAuth flag enabled</a>.</p>
|
||||
<h2 id="ticksize">TickSize</h2>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th align="left">Amendment ID</th>
|
||||
<th align="left">Status</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td align="left">532651B4FD58DF8922A49BA101AB3E996E5BFBF95A913B3E392504863E63B164</td>
|
||||
<td align="left">Enabled</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>Changes the way <a href="reference-transaction-format.html#lifecycle-of-an-offer">Offers</a> are ranked in order books, so that currency issuers can configure how many significant digits are taken into account when ranking Offers by exchange rate. With this amendment, the exchange rates of Offers are rounded to the configured number of significant digits, so that more Offers have the same exact exchange rate. The intent of this change is to require a meaningful improvement in price to outrank a previous Offer. If used by major issuers, this should reduce the incentive to spam the ledger with Offers that are only a tiny fraction of a percentage point better than existing offers. It may also increase the efficiency of order book storage in the ledger, because Offers can be grouped into fewer exchange rates.</p>
|
||||
<p>Introduces a <code>TickSize</code> field to accounts, which can be set with the <a href="reference-transaction-format.html#accountset">AccountSet transaction type</a>. If a currency issuer sets the <code>TickSize</code> field, the XRP Ledger truncates the exchange rate (ratio of funds in to funds out) of Offers to trade the issuer's currency, and adjusts the amounts of the Offer to match the truncated exchange rate. If only one currency in the trade has a <code>TickSize</code> set, that number of significant digits applies. When trading two currencies that have different <code>TickSize</code> values, whichever <code>TickSize</code> indicates the fewest significant digits applies. XRP does not have a <code>TickSize</code>.</p>
|
||||
<h2 id="tickets">Tickets</h2>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th align="left">Amendment ID</th>
|
||||
<th align="left">Status</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td align="left">C1B8D934087225F509BEB5A8EC24447854713EE447D277F69545ABFA0E0FD490</td>
|
||||
<td align="left">In development</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>Introduces Tickets as a way to reserve a transaction sequence number for later execution. Creates the <code>Ticket</code> ledger node type and the transaction types <code>TicketCreate</code> and <code>TicketCancel</code>.</p>
|
||||
<p class="devportal-callout caution"><strong>Caution:</strong> This amendment is still in development.</p>
|
||||
<!-- rippled release notes links -->
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<footer class="content-info" role="contentinfo">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-sm-12 absolute_bottom_footer">
|
||||
<div class="col-sm-8">
|
||||
<span>© 2013 - 2017 Ripple Labs, Inc. All Rights Reserved.</span>
|
||||
<span><a href="/terms-of-use/">Terms</a></span>
|
||||
<span><a href="/privacy-policy/">Privacy</a></span>
|
||||
</div>
|
||||
</div><!-- /.absolute_bottom_footer -->
|
||||
|
||||
</div><!-- /.row -->
|
||||
</div><!-- /.container -->
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,300 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<meta name="viewport" content="width=device-width">
|
||||
|
||||
<title>Consensus Process - Ripple Developer Portal</title>
|
||||
|
||||
<!-- favicon -->
|
||||
<link rel="icon" href="favicon.ico" type="image/x-icon">
|
||||
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon">
|
||||
|
||||
<!-- jQuery -->
|
||||
<script src="assets/vendor/jquery-1.11.1.min.js"></script>
|
||||
|
||||
<!-- Custom Stylesheets. ripple.css includes bootstrap, font stuff -->
|
||||
<link href="assets/css/ripple.css" rel="stylesheet" />
|
||||
<link href="assets/css/devportal.css" rel="stylesheet" />
|
||||
|
||||
<!-- Bootstrap JS -->
|
||||
<script src="assets/vendor/bootstrap.min.js"></script>
|
||||
|
||||
|
||||
<!-- syntax highlighting -->
|
||||
<link rel="stylesheet" href="assets/vendor/docco.min.css" />
|
||||
<script src="assets/vendor/highlight.min.js"></script>
|
||||
|
||||
<!-- syntax selection js -->
|
||||
<script src="assets/js/multicodetab.js"></script>
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
$(".multicode").minitabs();
|
||||
hljs.initHighlighting();
|
||||
make_code_expandable();
|
||||
});
|
||||
</script>
|
||||
|
||||
<script src="assets/js/expandcode.js"></script>
|
||||
<script src="assets/js/fixsidebarscroll.js"></script>
|
||||
|
||||
<!-- fontawesome icons -->
|
||||
<link rel="stylesheet" href="assets/vendor/fontawesome/css/font-awesome.min.css" />
|
||||
|
||||
</head>
|
||||
|
||||
<body class="page page-template page-template-template-dev-portal page-template-template-dev-portal-php sidebar-primary wpb-js-composer js-comp-ver-3.6.2 vc_responsive">
|
||||
<header role="banner" class="banner navbar navbar-default navbar-fixed-top initial_header">
|
||||
<div class="container">
|
||||
<div class="navbar-header">
|
||||
<a href="index.html" class="navbar-brand"><img src="assets/img/ripple-logo-color.png" class="logo"></a>
|
||||
</div><!-- /.navbar-header -->
|
||||
<div class="nav">
|
||||
<div class="draft-warning">DRAFT PAGE</div>
|
||||
</div><!-- /.nav -->
|
||||
|
||||
</div><!-- /.container -->
|
||||
|
||||
<div class="subnav dev_nav">
|
||||
<div class="container">
|
||||
<ul id="menu-dev-menu" class="menu">
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">References <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="reference-rippleapi.html">RippleAPI</a></li>
|
||||
<li><a href="reference-rippled.html">rippled</a></li>
|
||||
<li><a href="reference-transaction-format.html">Transaction Format</a></li>
|
||||
<li><a href="reference-ledger-format.html">Ledger Format</a></li>
|
||||
<li><a href="reference-data-api.html">Ripple Data API v2</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorials <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="tutorial-multisign.html">How to Multi-Sign</a></li>
|
||||
<li><a href="tutorial-paychan.html">Payment Channels Tutorial</a></li>
|
||||
<li><a href="concept-issuing-and-operational-addresses.html">Issuing and Operational Addresses</a></li>
|
||||
<li><a href="tutorial-reliable-transaction-submission.html">Reliable Transaction Submission</a></li>
|
||||
<li><a href="tutorial-rippleapi-beginners-guide.html">RippleAPI Beginners Guide</a></li>
|
||||
<li><a href="tutorial-rippled-setup.html">rippled Setup</a></li>
|
||||
<li><a href="tutorial-gateway-guide.html">Gateway Guide</a></li>
|
||||
<li><a href="tutorial-listing-xrp.html">Listing XRP as an Exchange</a></li>
|
||||
<li><a href="tutorial-escrow.html">Escrow Tutorials</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Features <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="concept-accounts.html">Accounts</a></li>
|
||||
<li><a href="concept-amendments.html">Amendments</a></li>
|
||||
<li><a href="concept-consensus.html">Consensus Process</a></li>
|
||||
<li><a href="concept-reaching-consensus.html">Reaching Consensus in the XRP Ledger</a></li>
|
||||
<li><a href="concept-fee-voting.html">Fee Voting</a></li>
|
||||
<li><a href="concept-fees.html">Fees (Disambiguation)</a></li>
|
||||
<li><a href="concept-freeze.html">Freeze</a></li>
|
||||
<li><a href="concept-partial-payments.html">Partial Payments</a></li>
|
||||
<li><a href="concept-paths.html">Paths</a></li>
|
||||
<li><a href="concept-reserves.html">Reserves</a></li>
|
||||
<li><a href="concept-stand-alone-mode.html">Stand-Alone Mode</a></li>
|
||||
<li><a href="concept-transaction-cost.html">Transaction Cost</a></li>
|
||||
<li><a href="concept-transfer-fees.html">Transfer Fees</a></li>
|
||||
<li><a href="concept-noripple.html">Understanding the NoRipple flag</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Gateway Bulletins <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="gb-2015-06.html">GB-2015-06: Corrections to Autobridging</a></li>
|
||||
<li><a href="gb-2015-05.html">GB-2015-05: Historical Ledger Query Migration</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">API Tools <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="ripple-api-tool.html">WebSocket API Tool</a></li>
|
||||
<li><a href="data-api-v2-tool.html">Data API v2 Tool</a></li>
|
||||
<li><a href="tool-jsonrpc.html">rippled JSON-RPC Tool</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li><a href="https://github.com/ripple/ripple-dev-portal" title="GitHub">Site Source</a></li>
|
||||
</ul><!-- /#dev-menu -->
|
||||
</div><!-- /.subnav .container -->
|
||||
</div><!-- /.subnav -->
|
||||
</header>
|
||||
|
||||
|
||||
<div class="wrap container" role="document">
|
||||
<aside class="sidebar" role="complementary">
|
||||
<div class="dev_nav_wrapper">
|
||||
<div id="cont">
|
||||
<h5>In this category:</h5>
|
||||
<ul class="dev_nav_sidebar">
|
||||
<li class="level-1"><a href="index.html">Category: Features</a></li>
|
||||
<li class="level-2"><a href="concept-accounts.html">Accounts</a></li>
|
||||
<li class="level-2"><a href="concept-amendments.html">Amendments</a></li>
|
||||
<li class="level-2"><a href="concept-consensus.html">Consensus Process</a></li>
|
||||
<li class="level-2"><a href="concept-reaching-consensus.html">Reaching Consensus in the XRP Ledger</a></li>
|
||||
<li class="level-2"><a href="concept-fee-voting.html">Fee Voting</a></li>
|
||||
<li class="level-2"><a href="concept-fees.html">Fees (Disambiguation)</a></li>
|
||||
<li class="level-2"><a href="concept-freeze.html">Freeze</a></li>
|
||||
<li class="level-2"><a href="concept-partial-payments.html">Partial Payments</a></li>
|
||||
<li class="level-2"><a href="concept-paths.html">Paths</a></li>
|
||||
<li class="level-2"><a href="concept-reserves.html">Reserves</a></li>
|
||||
<li class="level-2"><a href="concept-stand-alone-mode.html">Stand-Alone Mode</a></li>
|
||||
<li class="level-2"><a href="concept-transaction-cost.html">Transaction Cost</a></li>
|
||||
<li class="level-2"><a href="concept-transfer-fees.html">Transfer Fees</a></li>
|
||||
<li class="level-2"><a href="concept-noripple.html">Understanding the NoRipple flag</a></li>
|
||||
</ul>
|
||||
<hr />
|
||||
<h5>In this page:</h5>
|
||||
<ul class="dev_nav_sidebar" id="dactyl_toc_sidebar">
|
||||
<li class="level-1"><a href="#the-xrp-ledger-consensus-process">The XRP Ledger Consensus Process</a></li>
|
||||
<li class="level-2"><a href="#introduction">Introduction</a></li>
|
||||
<li class="level-2"><a href="#the-xrp-ledger-protocol-consensus-and-validation">The XRP Ledger Protocol – Consensus and Validation</a></li>
|
||||
<li class="level-3"><a href="#consensus">Consensus</a></li>
|
||||
<li class="level-3"><a href="#validation">Validation</a></li>
|
||||
<li class="level-2"><a href="#key-takeaways">Key Takeaways</a></li>
|
||||
<li class="level-2"><a href="#further-resources">Further Resources</a></li>
|
||||
<li class="level-2"><a href="#end-notes">End Notes</a></li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
<main class="main" role="main">
|
||||
<div class='content'>
|
||||
<h1 id="the-xrp-ledger-consensus-process">The XRP Ledger Consensus Process</h1>
|
||||
<p><em>Written by Dave Cohen, David Schwartz, and Arthur Britto.</em></p>
|
||||
<p>This article provides a high level overview of the XRP Ledger, the information it stores, and how <a href="reference-transaction-format.html">transactions</a> result in changes to the ledger.</p>
|
||||
<p>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.</p>
|
||||
<p class="devportal-callout caution"><strong>Caution:</strong> Transactions are not applied to the XRP Ledger instantaneously; it takes some time for the effects of transactions to be applied. During this process, <a href="reference-rippled.html"><code>rippled</code> APIs</a> may return provisional results that should not be mistaken for the final, immutable results of a transaction. Immutable results can only be determined by looking at validated ledgers.</p>
|
||||
<h2 id="introduction">Introduction</h2>
|
||||
<p>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:</p>
|
||||
<ul>
|
||||
<li>settings for each <a href="concept-accounts.html">account</a></li>
|
||||
<li>balances between accounts (trust lines)</li>
|
||||
<li>offers in the distributed exchange</li>
|
||||
<li>network settings, such as <a href="concept-transaction-cost.html">transaction costs</a> and <a href="concept-reserves.html">reserve</a> amounts</li>
|
||||
<li>a time stamp</li>
|
||||
</ul>
|
||||
<p>For a full, technical description of which data is included in a ledger version, see the <a href="reference-ledger-format.html">Ledger Format Reference</a>.</p>
|
||||
<p><a href="img/ledger-components.png"><img alt="Figure 1: XRP Ledger Elements" src="img/ledger-components.png"/></a></p>
|
||||
<p><em>Figure 1: XRP Ledger Elements</em></p>
|
||||
<p>The XRP Ledger has a new ledger version every several seconds. The ledger versions that preceded it comprise 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.</p>
|
||||
<p><a href="img/ledger-history.png"><img alt="Figure 2: XRP Ledger Sequence and History" src="img/ledger-history.png"/></a></p>
|
||||
<p><em>Figure 2: XRP Ledger Sequence and History</em></p>
|
||||
<p>A ledger instance is identified by its <em>sequence number</em> <a href="#footnote_1" id="footnote_from_1"><sup>1</sup></a>, also called a <em>ledger index</em>. Ledgers are numbered incrementally. If the last validated ledger is N, the previous was N-1 and the next will be N+1. The N+1 ledger is produced by applying a set of transactions to ledger N.</p>
|
||||
<p>User level changes to the ledger are the results of transactions. Examples of <a href="reference-transaction-format.html">transactions</a> include payments, changes to account settings or trust lines, and offers to trade. Each transaction authorizes changes to the ledger and is cryptographically signed by an account owner. Transactions are the only way to authorize changes to an account.</p>
|
||||
<p>A ledger instance also contains a set of transactions and metadata about those transactions. The transactions are those that have been applied to the prior ledger in order to create the new instance. The metadata records precisely the effects of the transaction on the ledger.</p>
|
||||
<p><a href="img/ledger-changes.png"><img alt="Figure 3: Transactions Applied to Ledger Version" src="img/ledger-changes.png"/></a></p>
|
||||
<p><em>Figure 3: Transactions Applied to Ledger Version</em></p>
|
||||
<p>The set of transactions included in a ledger instance are recorded in that ledger and allow auditability 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.</p>
|
||||
<p>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 will have the <strong>tesSUCCESS</strong> <a href="reference-transaction-format.html#transaction-results">result code</a> which indicates the requested changes are applied to the ledger and a fee was claimed. Other transactions in the ledger have <strong>tec</strong> class result codes, which indicate transactions that only claim a fee and perform no other changes <a href="#footnote_2" id="footnote_from_2"><sup>2</sup></a>.</p>
|
||||
<p>Transactions of the <strong>tec</strong> class are included with the ledger because they change an account balance when claiming a fee.</p>
|
||||
<p>In addition to the <strong>tes</strong> and <strong>tec</strong> class result codes, there are <strong>ter</strong>, <strong>tef</strong> and <strong>tem</strong> class codes. The latter three indicate provisional failures returned by API calls. Only <strong>tes</strong> and <strong>tec</strong> codes appear in ledgers.</p>
|
||||
<p>When working with <a href="reference-rippled.html"><code>rippled</code> APIs</a>, 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 or may not ever be included in a validated ledger.</p>
|
||||
<p>Important: Some <a href="reference-rippled.html"><code>rippled</code> APIs</a> provide provisional results, based on candidate transactions <a href="#footnote_3" id="footnote_from_3"><sup>3</sup></a>. 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 <a href="reference-transaction-format.html#lastledgersequence"><code>LastLedgerSequence</code></a> has been validated, yet the transaction does not appear in that ledger or any before it, then that transaction has failed and will never appear in any ledger. An outcome is final only for transactions that appear in a validated ledger or can never appear because of <code>LastLedgerSequence</code> restrictions as explained later in this document.</p>
|
||||
<h2 id="the-xrp-ledger-protocol-consensus-and-validation">The XRP Ledger Protocol – Consensus and Validation</h2>
|
||||
<p>The peer-to-peer XRP Ledger network consists of many distributed servers, called nodes, that accept and process transactions. Client applications sign and send transactions to nodes, 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.</p>
|
||||
<p><a href="img/xrp-ledger-network.png"><img alt="Figure 4: Participants in the XRP Ledger Protocol" src="img/xrp-ledger-network.png"/></a></p>
|
||||
<p><em>Figure 4: Participants in the XRP Ledger Protocol</em></p>
|
||||
<p>The nodes that receive, relay and process transactions may be either tracking nodes or validating nodes. Tracking nodes’ primary functions include distributing transactions from clients and responding to queries about the ledger. Validating nodes perform the same functions as tracking nodes and additionally contribute to advancing the ledger sequence <a href="#footnote_4" id="footnote_from_4"><sup>4</sup></a>.</p>
|
||||
<p>While accepting transactions submitted by client applications, each tracking node uses the last validated ledger as a starting point. The accepted transactions are candidates. The nodes 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 nodes, allowing each to consider an identical set of transactions to apply to the last validated ledger. As transactions take time to propagate however, the nodes do not work with an identical set of candidate transactions at all times. To account for this, the XRP Ledger uses a process called consensus to ensure that identical transactions are processed and validated ledgers are consistent across the peer-to-peer XRP Ledger network.</p>
|
||||
<h3 id="consensus">Consensus</h3>
|
||||
<p>The nodes on the network share information about candidate transactions. Through the consensus process, validating nodes agree on a specific subset of the candidate transactions to be considered for the next ledger. Consensus is an iterative process in which nodes relay proposals, or sets of candidate transactions. Nodes communicate and update proposals until a supermajority <a href="#footnote_5" id="footnote_from_5"><sup>5</sup></a> of peers agree on the same set of candidate transactions.</p>
|
||||
<p>During consensus, each node evaluates proposals from a specific set of peers, called chosen validators <a href="#footnote_6" id="footnote_from_6"><sup>6</sup></a>. Chosen validators represent a subset of the network which, when taken collectively, is "trusted" not to collude in an attempt to defraud the node 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 <a href="#footnote_7" id="footnote_from_7"><sup>7</sup></a>.</p>
|
||||
<p><a href="img/consensus-candidate-transaction-sets.png"><img alt="Figure 5: Validators Propose Transaction Sets" src="img/consensus-candidate-transaction-sets.png"/></a></p>
|
||||
<p><em>Figure 5: Validators Propose Transaction Sets — At the start of consensus, nodes work with different sets of transactions. Rounds of proposals determine which transactions will be applied to the ledger, and which must wait for a subsequent round of consensus.</em></p>
|
||||
<p>Candidate transactions which fail to be included in the agreed-upon proposal remain candidate transactions. They may be considered again in the next round of consensus.</p>
|
||||
<p><a href="img/consensus-agreed-transaction-set.png"><img alt="Figure 6: Through Consensus, Nodes Agree on Transaction Set" src="img/consensus-agreed-transaction-set.png"/></a></p>
|
||||
<p><em>Figure 6: Through Consensus, Nodes Agree On Transaction Set — Nodes will apply the agreed-upon set of transactions (shown in green) to the last validated ledger. Transactions not in the set (in red) may be agreed upon in the next round.</em></p>
|
||||
<p>Typically, a transaction which does not pass one round of consensus will succeed in the following round. However, in some circumstances, a transaction could fail to pass consensus indefinitely. One such circumstance is if the network increases the base fee to a value higher than the transaction provides. The transaction could potentially succeed if the fees are lowered at some point in the future.</p>
|
||||
<p>The <a href="reference-transaction-format.html#lastledgersequence"><code>LastLedgerSequence</code> transaction field</a> is a mechanism to prevent such a transaction from being viable indefinitely and ensure transaction processing occurs in a timely fashion. Applications should include a <code>LastLedgerSequence</code> parameter with each transaction. This ensures a transaction will either succeed or fail on or before the specified ledger sequence number, thus limiting the amount of time an application must wait before obtaining a definitive transaction result. For more information, see <a href="tutorial-reliable-transaction-submission.html">Reliable Transaction Submission</a>.</p>
|
||||
<h3 id="validation">Validation</h3>
|
||||
<p>When a round of consensus completes, each node computes a new ledger by applying the candidate transactions in the consensus transaction set to the last validated ledger.</p>
|
||||
<p><a href="img/consensus-calculate-validation.png"><img alt="Figure 7: A Network Node Calculates a Ledger Validation" src="img/consensus-calculate-validation.png"/></a></p>
|
||||
<p><em>Figure 7: A Network Node Calculates a Ledger Validation — Each tracking node applies agreed-upon transactions to the last validated ledger. Validating nodes will transmit their results to the entire network.</em></p>
|
||||
<p>The validating nodes calculate a new version of the ledger and relay their results to the network, each transmitting a signed hash of the ledger it calculated based on the candidate transactions proposed during consensus. These signed hashes, called validations, allow each node to compare the ledger it computed with those of its peers.</p>
|
||||
<p><a href="img/consensus-declare-validation.png"><img alt="Figure 8: Ledger is Validated When Supermajority of Peers Calculate an Identical Result" src="img/consensus-declare-validation.png"/></a></p>
|
||||
<p><em>Figure 8: Ledger is Validated When Supermajority of Peers Calculate an Identical Result — Nodes compare their calculated ledger with the hashes received from chosen validators. If not in agreement, the node must re-calculate or retrieve the correct ledger.</em></p>
|
||||
<p>Nodes of the network recognize a ledger instance as validated when a supermajority of the peers have signed and broadcast an identical validation hash <a href="#footnote_8" id="footnote_from_8"><sup>8</sup></a>. Going forward, transactions will be applied to this updated and now validated ledger with sequence number N+1.</p>
|
||||
<p>In cases where a node is in the minority, having computed a ledger that differs from its peers, the node will disregard the ledger it computed <a href="#footnote_9" id="footnote_from_9"><sup>9</sup></a>. It will recompute the correct ledger, or retrieve the correct ledger as needed.</p>
|
||||
<p>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 nodes repeat the consensus process. As time passes since consensus began, it becomes increasingly likely that a majority of the nodes have received the same set of candidate transactions, as each consensus round reduces disagreement. The XRP Ledger dynamically adjusts <a href="concept-transaction-cost.html">transaction costs</a> and the time to wait for consensus in response to these conditions.</p>
|
||||
<p><a href="img/consensus-validated-ledger.png"><img alt="Figure 9: Network Recognizes a New Validated Ledger Version" src="img/consensus-validated-ledger.png"/></a></p>
|
||||
<p><em>Figure 9: Network Recognises the New Validated Ledger Version — At the end of a round of the consensus process, nodes have an updated validated ledger.</em></p>
|
||||
<p>Once they reach supermajority agreement on validations, the nodes work with the new validated ledger, sequence number N+1. The consensus and validation process repeats <a href="#footnote_10" id="footnote_from_10"><sup>10</sup></a>, considering candidate transactions that were not included in the last round along with new transactions submitted in the meantime.</p>
|
||||
<h2 id="key-takeaways">Key Takeaways</h2>
|
||||
<p>Transactions submitted to the XRP Ledger are not processed instantaneously. For a period of time, each transaction remains a candidate.</p>
|
||||
<p>The lifecycle of a single transaction is as follows:</p>
|
||||
<ul>
|
||||
<li>A transaction is created and signed by an account owner.</li>
|
||||
<li>The transaction is submitted to the network.<ul>
|
||||
<li>Badly formed transactions may be rejected immediately.</li>
|
||||
<li>Well formed transactions may provisionally succeed, then later fail.</li>
|
||||
<li>Well formed transactions may provisionally fail, then later succeed.</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>During consensus, the transaction is included in the ledger.<ul>
|
||||
<li>The result of a successful consensus round is a validated ledger.</li>
|
||||
<li>If a consensus round fails, the consensus process repeats until it succeeds.</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>The validated ledger includes the transaction and its effects on the ledger state.</li>
|
||||
</ul>
|
||||
<p>Applications should only rely on information in validated ledgers, not on the provisional results of candidate transactions. Some <a href="reference-rippled.html"><code>rippled</code> APIs</a> 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 <code>LastLedgerSequence</code> and does not appear in any validated ledger with that sequence number or lower.</p>
|
||||
<p>Best practices for applications submitting transactions include:</p>
|
||||
<ul>
|
||||
<li>Use the <code>LastLedgerSequence</code> parameter to ensure that transactions validate or fail in a deterministic and timely fashion.</li>
|
||||
<li>Check the results of transactions in validated ledgers.<ul>
|
||||
<li>Until a ledger containing the transaction is validated, or <code>LastLedgerSequence</code> has passed, results are provisional.</li>
|
||||
<li>Transactions with result code <strong>tesSUCCESS</strong> and <code>"validated": true</code> have immutably succeeded.</li>
|
||||
<li>Transactions with other result codes and <code>"validated": true</code> have immutably failed.</li>
|
||||
<li>Transactions that fail to appear in any validated ledger up to and including the validated ledger identified by the transaction’s <code>LastLedgerSequence</code> have immutably failed.<ul>
|
||||
<li>Take care to use a node with a continuous ledger history to detect this case <a href="#footnote_11" id="footnote_from_11"><sup>11</sup></a>.</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>It may be necessary to check the status of a transaction repeatedly until the ledger identified by <code>LastLedgerSequence</code> is validated.</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<h2 id="further-resources">Further Resources</h2>
|
||||
<ul>
|
||||
<li><a href="https://ripple.com/files/ripple_consensus_whitepaper.pdf">Consensus White Paper</a></li>
|
||||
<li><a href="reference-ledger-format.html">Ledger Format Reference</a></li>
|
||||
<li><a href="https://www.youtube.com/watch?v=pj1QVb1vlC0">Ripple Consensus Video</a></li>
|
||||
<li><a href="tutorial-reliable-transaction-submission.html">Reliable Transaction Submission</a></li>
|
||||
</ul>
|
||||
<h2 id="end-notes">End Notes</h2>
|
||||
<p><a href="#footnote_from_1" id="footnote_1"><sup>1</sup></a> – A ledger instance can also be uniquely identified by its hash, which is a digital fingerprint of its contents.</p>
|
||||
<p><a href="#footnote_from_2" id="footnote_2"><sup>2</sup></a> – Transactions with <strong>tec</strong> result codes are included in ledgers and not do the requested action. The rationale for this is that multiple transactions may be submitted in sequence, with the order of processing determined by a sequence number associated with an account (not to be confused with the ledger sequence number). To prevent a hold on account sequence numbers which would block subsequent transactions, the transaction is processed to consume the sequence number. Additionally, transactions which are distributed to the network must claim a fee to prevent network abuse.</p>
|
||||
<p><a href="#footnote_from_3" id="footnote_3"><sup>3</sup></a> – 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 will return $0. This value is based on the provisional result of a candidate transaction. There are circumstances in which the payment will fail and Alice’s balance will remain $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 <strong>tesSUCCESS</strong>. If the transaction is in a validated ledger with any other result code, the payment has failed.</p>
|
||||
<p><a href="#footnote_from_4" id="footnote_4"><sup>4</sup></a> – Strictly speaking, validating nodes are a subset of tracking nodes. They provide the same features and additionally create "validations." Tracking nodes may be further categorized by whether they maintain full vs. partial ledger history.</p>
|
||||
<p><a href="#footnote_from_5" id="footnote_5"><sup>5</sup></a> – 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</p>
|
||||
<p><a href="#footnote_from_6" id="footnote_6"><sup>6</sup></a> – Sometimes referred to as a Unique Node List (UNL).</p>
|
||||
<p><a href="#footnote_from_7" id="footnote_7"><sup>7</sup></a> – If proposals from all validators were evaluated, instead of exclusively from the validators chosen not to collude, a malicious attacker could spin up enough validating nodes to comprise a colluding supermajority to introduce invalid transactions or omit valid transactions from proposals. The chosen validator list defends against Sybil attacks.</p>
|
||||
<p><a href="#footnote_from_8" id="footnote_8"><sup>8</sup></a> – 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.</p>
|
||||
<p><a href="#footnote_from_9" id="footnote_9"><sup>9</sup></a> – In practice, the node 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 will not meet the 80% threshold. At that point, it can begin to recalculate a ledger.</p>
|
||||
<p><a href="#footnote_from_10" id="footnote_10"><sup>10</sup></a> – In practice, the XRP Ledger runs more efficiently by starting a new round of consensus concurrently, before validation has completed.</p>
|
||||
<p><a href="#footnote_from_11" id="footnote_11"><sup>11</sup></a> – A <code>rippled</code> 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 node’s ledger history. Over time, if configured to, rippled will fill in gaps in its history. When testing for missing transactions, it is important to verify against a node with continuous complete ledgers from the time the transaction was submitted until its LastLedgerSequence. Use the RPC server_state to determine which complete_ledgers are available to a particular node.</p>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<footer class="content-info" role="contentinfo">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-sm-12 absolute_bottom_footer">
|
||||
<div class="col-sm-8">
|
||||
<span>© 2013 - 2017 Ripple Labs, Inc. All Rights Reserved.</span>
|
||||
<span><a href="/terms-of-use/">Terms</a></span>
|
||||
<span><a href="/privacy-policy/">Privacy</a></span>
|
||||
</div>
|
||||
</div><!-- /.absolute_bottom_footer -->
|
||||
|
||||
</div><!-- /.row -->
|
||||
</div><!-- /.container -->
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,221 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<meta name="viewport" content="width=device-width">
|
||||
|
||||
<title>Fee Voting - Ripple Developer Portal</title>
|
||||
|
||||
<!-- favicon -->
|
||||
<link rel="icon" href="favicon.ico" type="image/x-icon">
|
||||
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon">
|
||||
|
||||
<!-- jQuery -->
|
||||
<script src="assets/vendor/jquery-1.11.1.min.js"></script>
|
||||
|
||||
<!-- Custom Stylesheets. ripple.css includes bootstrap, font stuff -->
|
||||
<link href="assets/css/ripple.css" rel="stylesheet" />
|
||||
<link href="assets/css/devportal.css" rel="stylesheet" />
|
||||
|
||||
<!-- Bootstrap JS -->
|
||||
<script src="assets/vendor/bootstrap.min.js"></script>
|
||||
|
||||
|
||||
<!-- syntax highlighting -->
|
||||
<link rel="stylesheet" href="assets/vendor/docco.min.css" />
|
||||
<script src="assets/vendor/highlight.min.js"></script>
|
||||
|
||||
<!-- syntax selection js -->
|
||||
<script src="assets/js/multicodetab.js"></script>
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
$(".multicode").minitabs();
|
||||
hljs.initHighlighting();
|
||||
make_code_expandable();
|
||||
});
|
||||
</script>
|
||||
|
||||
<script src="assets/js/expandcode.js"></script>
|
||||
<script src="assets/js/fixsidebarscroll.js"></script>
|
||||
|
||||
<!-- fontawesome icons -->
|
||||
<link rel="stylesheet" href="assets/vendor/fontawesome/css/font-awesome.min.css" />
|
||||
|
||||
</head>
|
||||
|
||||
<body class="page page-template page-template-template-dev-portal page-template-template-dev-portal-php sidebar-primary wpb-js-composer js-comp-ver-3.6.2 vc_responsive">
|
||||
<header role="banner" class="banner navbar navbar-default navbar-fixed-top initial_header">
|
||||
<div class="container">
|
||||
<div class="navbar-header">
|
||||
<a href="index.html" class="navbar-brand"><img src="assets/img/ripple-logo-color.png" class="logo"></a>
|
||||
</div><!-- /.navbar-header -->
|
||||
<div class="nav">
|
||||
<div class="draft-warning">DRAFT PAGE</div>
|
||||
</div><!-- /.nav -->
|
||||
|
||||
</div><!-- /.container -->
|
||||
|
||||
<div class="subnav dev_nav">
|
||||
<div class="container">
|
||||
<ul id="menu-dev-menu" class="menu">
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">References <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="reference-rippleapi.html">RippleAPI</a></li>
|
||||
<li><a href="reference-rippled.html">rippled</a></li>
|
||||
<li><a href="reference-transaction-format.html">Transaction Format</a></li>
|
||||
<li><a href="reference-ledger-format.html">Ledger Format</a></li>
|
||||
<li><a href="reference-data-api.html">Ripple Data API v2</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorials <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="tutorial-multisign.html">How to Multi-Sign</a></li>
|
||||
<li><a href="tutorial-paychan.html">Payment Channels Tutorial</a></li>
|
||||
<li><a href="concept-issuing-and-operational-addresses.html">Issuing and Operational Addresses</a></li>
|
||||
<li><a href="tutorial-reliable-transaction-submission.html">Reliable Transaction Submission</a></li>
|
||||
<li><a href="tutorial-rippleapi-beginners-guide.html">RippleAPI Beginners Guide</a></li>
|
||||
<li><a href="tutorial-rippled-setup.html">rippled Setup</a></li>
|
||||
<li><a href="tutorial-gateway-guide.html">Gateway Guide</a></li>
|
||||
<li><a href="tutorial-listing-xrp.html">Listing XRP as an Exchange</a></li>
|
||||
<li><a href="tutorial-escrow.html">Escrow Tutorials</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Features <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="concept-accounts.html">Accounts</a></li>
|
||||
<li><a href="concept-amendments.html">Amendments</a></li>
|
||||
<li><a href="concept-consensus.html">Consensus Process</a></li>
|
||||
<li><a href="concept-reaching-consensus.html">Reaching Consensus in the XRP Ledger</a></li>
|
||||
<li><a href="concept-fee-voting.html">Fee Voting</a></li>
|
||||
<li><a href="concept-fees.html">Fees (Disambiguation)</a></li>
|
||||
<li><a href="concept-freeze.html">Freeze</a></li>
|
||||
<li><a href="concept-partial-payments.html">Partial Payments</a></li>
|
||||
<li><a href="concept-paths.html">Paths</a></li>
|
||||
<li><a href="concept-reserves.html">Reserves</a></li>
|
||||
<li><a href="concept-stand-alone-mode.html">Stand-Alone Mode</a></li>
|
||||
<li><a href="concept-transaction-cost.html">Transaction Cost</a></li>
|
||||
<li><a href="concept-transfer-fees.html">Transfer Fees</a></li>
|
||||
<li><a href="concept-noripple.html">Understanding the NoRipple flag</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Gateway Bulletins <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="gb-2015-06.html">GB-2015-06: Corrections to Autobridging</a></li>
|
||||
<li><a href="gb-2015-05.html">GB-2015-05: Historical Ledger Query Migration</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">API Tools <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="ripple-api-tool.html">WebSocket API Tool</a></li>
|
||||
<li><a href="data-api-v2-tool.html">Data API v2 Tool</a></li>
|
||||
<li><a href="tool-jsonrpc.html">rippled JSON-RPC Tool</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li><a href="https://github.com/ripple/ripple-dev-portal" title="GitHub">Site Source</a></li>
|
||||
</ul><!-- /#dev-menu -->
|
||||
</div><!-- /.subnav .container -->
|
||||
</div><!-- /.subnav -->
|
||||
</header>
|
||||
|
||||
|
||||
<div class="wrap container" role="document">
|
||||
<aside class="sidebar" role="complementary">
|
||||
<div class="dev_nav_wrapper">
|
||||
<div id="cont">
|
||||
<h5>In this category:</h5>
|
||||
<ul class="dev_nav_sidebar">
|
||||
<li class="level-1"><a href="index.html">Category: Features</a></li>
|
||||
<li class="level-2"><a href="concept-accounts.html">Accounts</a></li>
|
||||
<li class="level-2"><a href="concept-amendments.html">Amendments</a></li>
|
||||
<li class="level-2"><a href="concept-consensus.html">Consensus Process</a></li>
|
||||
<li class="level-2"><a href="concept-reaching-consensus.html">Reaching Consensus in the XRP Ledger</a></li>
|
||||
<li class="level-2"><a href="concept-fee-voting.html">Fee Voting</a></li>
|
||||
<li class="level-2"><a href="concept-fees.html">Fees (Disambiguation)</a></li>
|
||||
<li class="level-2"><a href="concept-freeze.html">Freeze</a></li>
|
||||
<li class="level-2"><a href="concept-partial-payments.html">Partial Payments</a></li>
|
||||
<li class="level-2"><a href="concept-paths.html">Paths</a></li>
|
||||
<li class="level-2"><a href="concept-reserves.html">Reserves</a></li>
|
||||
<li class="level-2"><a href="concept-stand-alone-mode.html">Stand-Alone Mode</a></li>
|
||||
<li class="level-2"><a href="concept-transaction-cost.html">Transaction Cost</a></li>
|
||||
<li class="level-2"><a href="concept-transfer-fees.html">Transfer Fees</a></li>
|
||||
<li class="level-2"><a href="concept-noripple.html">Understanding the NoRipple flag</a></li>
|
||||
</ul>
|
||||
<hr />
|
||||
<h5>In this page:</h5>
|
||||
<ul class="dev_nav_sidebar" id="dactyl_toc_sidebar">
|
||||
<li class="level-1"><a href="#fee-voting">Fee Voting</a></li>
|
||||
<li class="level-2"><a href="#voting-process">Voting Process</a></li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
<main class="main" role="main">
|
||||
<div class='content'>
|
||||
<h1 id="fee-voting">Fee Voting</h1>
|
||||
<p>Validators can vote for changes to basic <a href="concept-transaction-cost.html">transaction cost</a> as well as <a href="concept-reserves.html">reserve requirements</a>. 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.</p>
|
||||
<p>Operators of <a href="tutorial-rippled-setup.html#running-a-validator"><code>rippled</code> validators</a> can set their preferences for the transaction cost and reserve requirements in the <code>[voting]</code> stanza of the <code>rippled.cfg</code> file. <strong>Caution:</strong> insufficient requirements could expose the XRP Ledger peer-to-peer network to denial-of-service attacks. The parameters you can set are as follows:</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Parameter</th>
|
||||
<th>Description</th>
|
||||
<th>Recommended Value</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>reference_fee</td>
|
||||
<td>Amount of XRP, in <em>drops</em>, that must be destroyed to send the reference transaction, the cheapest possible transaction. (1 XRP = 1 million drops.) The actual transaction cost is a multiple of this value, scaled dynamically based on the load of individual servers.</td>
|
||||
<td><code>10</code> (0.00001 XRP)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>account_reserve</td>
|
||||
<td>Minimum amount of XRP, in <em>drops</em>, that an account must have on reserve. This is the smallest amount that can be sent to fund a new account in the ledger.</td>
|
||||
<td><code>20000000</code> (20 XRP)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>owner_reserve</td>
|
||||
<td>How much more XRP, in <em>drops</em>, that an address must hold for <em>each</em> object it owns in the ledger.</td>
|
||||
<td><code>5000000</code> (5 XRP)</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h2 id="voting-process">Voting Process</h2>
|
||||
<p>Every 256th ledger is called a "flag" ledger. (A flag ledger is defined such that the <code>ledger_index</code> <a href="https://en.wikipedia.org/wiki/Modulo_operation">modulo</a> <code>256</code> is equal to <code>0</code>.) 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.</p>
|
||||
<p>In the flag ledger itself, nothing happens, but validators receive and take note of the votes from other validators they trust.</p>
|
||||
<p>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 <a href="reference-transaction-format.html#setfee">SetFee pseudo-transaction</a> 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 psuedo-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.</p>
|
||||
<p>In short:</p>
|
||||
<ul>
|
||||
<li><strong>Flag ledger -1</strong>: Validators submit votes.</li>
|
||||
<li><strong>Flag ledger</strong>: Validators tally votes and decide what SetFee to include, if any.</li>
|
||||
<li><strong>Flag ledger +1</strong>: Validators insert SetFee pseudo-transaction into their proposed ledgers.</li>
|
||||
<li><strong>Flag ledger +2</strong>: New settings take effect, if a SetFee psuedotransaction achieved consensus.</li>
|
||||
</ul>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<footer class="content-info" role="contentinfo">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-sm-12 absolute_bottom_footer">
|
||||
<div class="col-sm-8">
|
||||
<span>© 2013 - 2017 Ripple Labs, Inc. All Rights Reserved.</span>
|
||||
<span><a href="/terms-of-use/">Terms</a></span>
|
||||
<span><a href="/privacy-policy/">Privacy</a></span>
|
||||
</div>
|
||||
</div><!-- /.absolute_bottom_footer -->
|
||||
|
||||
</div><!-- /.row -->
|
||||
</div><!-- /.container -->
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,197 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<meta name="viewport" content="width=device-width">
|
||||
|
||||
<title>Fees (Disambiguation) - Ripple Developer Portal</title>
|
||||
|
||||
<!-- favicon -->
|
||||
<link rel="icon" href="favicon.ico" type="image/x-icon">
|
||||
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon">
|
||||
|
||||
<!-- jQuery -->
|
||||
<script src="assets/vendor/jquery-1.11.1.min.js"></script>
|
||||
|
||||
<!-- Custom Stylesheets. ripple.css includes bootstrap, font stuff -->
|
||||
<link href="assets/css/ripple.css" rel="stylesheet" />
|
||||
<link href="assets/css/devportal.css" rel="stylesheet" />
|
||||
|
||||
<!-- Bootstrap JS -->
|
||||
<script src="assets/vendor/bootstrap.min.js"></script>
|
||||
|
||||
|
||||
<!-- syntax highlighting -->
|
||||
<link rel="stylesheet" href="assets/vendor/docco.min.css" />
|
||||
<script src="assets/vendor/highlight.min.js"></script>
|
||||
|
||||
<!-- syntax selection js -->
|
||||
<script src="assets/js/multicodetab.js"></script>
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
$(".multicode").minitabs();
|
||||
hljs.initHighlighting();
|
||||
make_code_expandable();
|
||||
});
|
||||
</script>
|
||||
|
||||
<script src="assets/js/expandcode.js"></script>
|
||||
<script src="assets/js/fixsidebarscroll.js"></script>
|
||||
|
||||
<!-- fontawesome icons -->
|
||||
<link rel="stylesheet" href="assets/vendor/fontawesome/css/font-awesome.min.css" />
|
||||
|
||||
</head>
|
||||
|
||||
<body class="page page-template page-template-template-dev-portal page-template-template-dev-portal-php sidebar-primary wpb-js-composer js-comp-ver-3.6.2 vc_responsive">
|
||||
<header role="banner" class="banner navbar navbar-default navbar-fixed-top initial_header">
|
||||
<div class="container">
|
||||
<div class="navbar-header">
|
||||
<a href="index.html" class="navbar-brand"><img src="assets/img/ripple-logo-color.png" class="logo"></a>
|
||||
</div><!-- /.navbar-header -->
|
||||
<div class="nav">
|
||||
<div class="draft-warning">DRAFT PAGE</div>
|
||||
</div><!-- /.nav -->
|
||||
|
||||
</div><!-- /.container -->
|
||||
|
||||
<div class="subnav dev_nav">
|
||||
<div class="container">
|
||||
<ul id="menu-dev-menu" class="menu">
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">References <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="reference-rippleapi.html">RippleAPI</a></li>
|
||||
<li><a href="reference-rippled.html">rippled</a></li>
|
||||
<li><a href="reference-transaction-format.html">Transaction Format</a></li>
|
||||
<li><a href="reference-ledger-format.html">Ledger Format</a></li>
|
||||
<li><a href="reference-data-api.html">Ripple Data API v2</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorials <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="tutorial-multisign.html">How to Multi-Sign</a></li>
|
||||
<li><a href="tutorial-paychan.html">Payment Channels Tutorial</a></li>
|
||||
<li><a href="concept-issuing-and-operational-addresses.html">Issuing and Operational Addresses</a></li>
|
||||
<li><a href="tutorial-reliable-transaction-submission.html">Reliable Transaction Submission</a></li>
|
||||
<li><a href="tutorial-rippleapi-beginners-guide.html">RippleAPI Beginners Guide</a></li>
|
||||
<li><a href="tutorial-rippled-setup.html">rippled Setup</a></li>
|
||||
<li><a href="tutorial-gateway-guide.html">Gateway Guide</a></li>
|
||||
<li><a href="tutorial-listing-xrp.html">Listing XRP as an Exchange</a></li>
|
||||
<li><a href="tutorial-escrow.html">Escrow Tutorials</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Features <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="concept-accounts.html">Accounts</a></li>
|
||||
<li><a href="concept-amendments.html">Amendments</a></li>
|
||||
<li><a href="concept-consensus.html">Consensus Process</a></li>
|
||||
<li><a href="concept-reaching-consensus.html">Reaching Consensus in the XRP Ledger</a></li>
|
||||
<li><a href="concept-fee-voting.html">Fee Voting</a></li>
|
||||
<li><a href="concept-fees.html">Fees (Disambiguation)</a></li>
|
||||
<li><a href="concept-freeze.html">Freeze</a></li>
|
||||
<li><a href="concept-partial-payments.html">Partial Payments</a></li>
|
||||
<li><a href="concept-paths.html">Paths</a></li>
|
||||
<li><a href="concept-reserves.html">Reserves</a></li>
|
||||
<li><a href="concept-stand-alone-mode.html">Stand-Alone Mode</a></li>
|
||||
<li><a href="concept-transaction-cost.html">Transaction Cost</a></li>
|
||||
<li><a href="concept-transfer-fees.html">Transfer Fees</a></li>
|
||||
<li><a href="concept-noripple.html">Understanding the NoRipple flag</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Gateway Bulletins <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="gb-2015-06.html">GB-2015-06: Corrections to Autobridging</a></li>
|
||||
<li><a href="gb-2015-05.html">GB-2015-05: Historical Ledger Query Migration</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">API Tools <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="ripple-api-tool.html">WebSocket API Tool</a></li>
|
||||
<li><a href="data-api-v2-tool.html">Data API v2 Tool</a></li>
|
||||
<li><a href="tool-jsonrpc.html">rippled JSON-RPC Tool</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li><a href="https://github.com/ripple/ripple-dev-portal" title="GitHub">Site Source</a></li>
|
||||
</ul><!-- /#dev-menu -->
|
||||
</div><!-- /.subnav .container -->
|
||||
</div><!-- /.subnav -->
|
||||
</header>
|
||||
|
||||
|
||||
<div class="wrap container" role="document">
|
||||
<aside class="sidebar" role="complementary">
|
||||
<div class="dev_nav_wrapper">
|
||||
<div id="cont">
|
||||
<h5>In this category:</h5>
|
||||
<ul class="dev_nav_sidebar">
|
||||
<li class="level-1"><a href="index.html">Category: Features</a></li>
|
||||
<li class="level-2"><a href="concept-accounts.html">Accounts</a></li>
|
||||
<li class="level-2"><a href="concept-amendments.html">Amendments</a></li>
|
||||
<li class="level-2"><a href="concept-consensus.html">Consensus Process</a></li>
|
||||
<li class="level-2"><a href="concept-reaching-consensus.html">Reaching Consensus in the XRP Ledger</a></li>
|
||||
<li class="level-2"><a href="concept-fee-voting.html">Fee Voting</a></li>
|
||||
<li class="level-2"><a href="concept-fees.html">Fees (Disambiguation)</a></li>
|
||||
<li class="level-2"><a href="concept-freeze.html">Freeze</a></li>
|
||||
<li class="level-2"><a href="concept-partial-payments.html">Partial Payments</a></li>
|
||||
<li class="level-2"><a href="concept-paths.html">Paths</a></li>
|
||||
<li class="level-2"><a href="concept-reserves.html">Reserves</a></li>
|
||||
<li class="level-2"><a href="concept-stand-alone-mode.html">Stand-Alone Mode</a></li>
|
||||
<li class="level-2"><a href="concept-transaction-cost.html">Transaction Cost</a></li>
|
||||
<li class="level-2"><a href="concept-transfer-fees.html">Transfer Fees</a></li>
|
||||
<li class="level-2"><a href="concept-noripple.html">Understanding the NoRipple flag</a></li>
|
||||
</ul>
|
||||
<hr />
|
||||
<h5>In this page:</h5>
|
||||
<ul class="dev_nav_sidebar" id="dactyl_toc_sidebar">
|
||||
<li class="level-1"><a href="#fees-disambiguation">Fees (Disambiguation)</a></li>
|
||||
<li class="level-2"><a href="#in-the-ledger">In the Ledger</a></li>
|
||||
<li class="level-3"><a href="#neutral-fees">Neutral Fees</a></li>
|
||||
<li class="level-3"><a href="#optional-fees">Optional Fees</a></li>
|
||||
<li class="level-2"><a href="#outside-the-ledger">Outside the Ledger</a></li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
<main class="main" role="main">
|
||||
<div class='content'>
|
||||
<h1 id="fees-disambiguation">Fees (Disambiguation)</h1>
|
||||
<p>The XRP Ledger is a decentralized ledger, secured by cryptography and operated 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.</p>
|
||||
<p>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.</p>
|
||||
<h2 id="in-the-ledger">In the Ledger</h2>
|
||||
<h3 id="neutral-fees">Neutral Fees</h3>
|
||||
<p>The <em><strong>transaction cost</strong></em> (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 <a href="concept-transaction-cost.html">Transaction Cost</a> for more information.</p>
|
||||
<p>The <em><strong>reserve requirement</strong></em> 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 <a href="concept-reserves.html">Reserves</a> for more information.</p>
|
||||
<h3 id="optional-fees">Optional Fees</h3>
|
||||
<p><em><strong>Transfer fees</strong></em> are optional percentage fees that issuers can charge to transfer the currencies they issue to other addresses within the XRP Ledger. See <a href="concept-transfer-fees.html">Transfer Fees</a> for more information.</p>
|
||||
<p><em><strong>Trust line quality</strong></em> 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.</p>
|
||||
<h2 id="outside-the-ledger">Outside the Ledger</h2>
|
||||
<p>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.</p>
|
||||
<p>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.</p>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<footer class="content-info" role="contentinfo">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-sm-12 absolute_bottom_footer">
|
||||
<div class="col-sm-8">
|
||||
<span>© 2013 - 2017 Ripple Labs, Inc. All Rights Reserved.</span>
|
||||
<span><a href="/terms-of-use/">Terms</a></span>
|
||||
<span><a href="/privacy-policy/">Privacy</a></span>
|
||||
</div>
|
||||
</div><!-- /.absolute_bottom_footer -->
|
||||
|
||||
</div><!-- /.row -->
|
||||
</div><!-- /.container -->
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,884 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<meta name="viewport" content="width=device-width">
|
||||
|
||||
<title>Freeze - Ripple Developer Portal</title>
|
||||
|
||||
<!-- favicon -->
|
||||
<link rel="icon" href="favicon.ico" type="image/x-icon">
|
||||
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon">
|
||||
|
||||
<!-- jQuery -->
|
||||
<script src="assets/vendor/jquery-1.11.1.min.js"></script>
|
||||
|
||||
<!-- Custom Stylesheets. ripple.css includes bootstrap, font stuff -->
|
||||
<link href="assets/css/ripple.css" rel="stylesheet" />
|
||||
<link href="assets/css/devportal.css" rel="stylesheet" />
|
||||
|
||||
<!-- Bootstrap JS -->
|
||||
<script src="assets/vendor/bootstrap.min.js"></script>
|
||||
|
||||
|
||||
<!-- syntax highlighting -->
|
||||
<link rel="stylesheet" href="assets/vendor/docco.min.css" />
|
||||
<script src="assets/vendor/highlight.min.js"></script>
|
||||
|
||||
<!-- syntax selection js -->
|
||||
<script src="assets/js/multicodetab.js"></script>
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
$(".multicode").minitabs();
|
||||
hljs.initHighlighting();
|
||||
make_code_expandable();
|
||||
});
|
||||
</script>
|
||||
|
||||
<script src="assets/js/expandcode.js"></script>
|
||||
<script src="assets/js/fixsidebarscroll.js"></script>
|
||||
|
||||
<!-- fontawesome icons -->
|
||||
<link rel="stylesheet" href="assets/vendor/fontawesome/css/font-awesome.min.css" />
|
||||
|
||||
</head>
|
||||
|
||||
<body class="page page-template page-template-template-dev-portal page-template-template-dev-portal-php sidebar-primary wpb-js-composer js-comp-ver-3.6.2 vc_responsive">
|
||||
<header role="banner" class="banner navbar navbar-default navbar-fixed-top initial_header">
|
||||
<div class="container">
|
||||
<div class="navbar-header">
|
||||
<a href="index.html" class="navbar-brand"><img src="assets/img/ripple-logo-color.png" class="logo"></a>
|
||||
</div><!-- /.navbar-header -->
|
||||
<div class="nav">
|
||||
<div class="draft-warning">DRAFT PAGE</div>
|
||||
</div><!-- /.nav -->
|
||||
|
||||
</div><!-- /.container -->
|
||||
|
||||
<div class="subnav dev_nav">
|
||||
<div class="container">
|
||||
<ul id="menu-dev-menu" class="menu">
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">References <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="reference-rippleapi.html">RippleAPI</a></li>
|
||||
<li><a href="reference-rippled.html">rippled</a></li>
|
||||
<li><a href="reference-transaction-format.html">Transaction Format</a></li>
|
||||
<li><a href="reference-ledger-format.html">Ledger Format</a></li>
|
||||
<li><a href="reference-data-api.html">Ripple Data API v2</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorials <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="tutorial-multisign.html">How to Multi-Sign</a></li>
|
||||
<li><a href="tutorial-paychan.html">Payment Channels Tutorial</a></li>
|
||||
<li><a href="concept-issuing-and-operational-addresses.html">Issuing and Operational Addresses</a></li>
|
||||
<li><a href="tutorial-reliable-transaction-submission.html">Reliable Transaction Submission</a></li>
|
||||
<li><a href="tutorial-rippleapi-beginners-guide.html">RippleAPI Beginners Guide</a></li>
|
||||
<li><a href="tutorial-rippled-setup.html">rippled Setup</a></li>
|
||||
<li><a href="tutorial-gateway-guide.html">Gateway Guide</a></li>
|
||||
<li><a href="tutorial-listing-xrp.html">Listing XRP as an Exchange</a></li>
|
||||
<li><a href="tutorial-escrow.html">Escrow Tutorials</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Features <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="concept-accounts.html">Accounts</a></li>
|
||||
<li><a href="concept-amendments.html">Amendments</a></li>
|
||||
<li><a href="concept-consensus.html">Consensus Process</a></li>
|
||||
<li><a href="concept-reaching-consensus.html">Reaching Consensus in the XRP Ledger</a></li>
|
||||
<li><a href="concept-fee-voting.html">Fee Voting</a></li>
|
||||
<li><a href="concept-fees.html">Fees (Disambiguation)</a></li>
|
||||
<li><a href="concept-freeze.html">Freeze</a></li>
|
||||
<li><a href="concept-partial-payments.html">Partial Payments</a></li>
|
||||
<li><a href="concept-paths.html">Paths</a></li>
|
||||
<li><a href="concept-reserves.html">Reserves</a></li>
|
||||
<li><a href="concept-stand-alone-mode.html">Stand-Alone Mode</a></li>
|
||||
<li><a href="concept-transaction-cost.html">Transaction Cost</a></li>
|
||||
<li><a href="concept-transfer-fees.html">Transfer Fees</a></li>
|
||||
<li><a href="concept-noripple.html">Understanding the NoRipple flag</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Gateway Bulletins <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="gb-2015-06.html">GB-2015-06: Corrections to Autobridging</a></li>
|
||||
<li><a href="gb-2015-05.html">GB-2015-05: Historical Ledger Query Migration</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">API Tools <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="ripple-api-tool.html">WebSocket API Tool</a></li>
|
||||
<li><a href="data-api-v2-tool.html">Data API v2 Tool</a></li>
|
||||
<li><a href="tool-jsonrpc.html">rippled JSON-RPC Tool</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li><a href="https://github.com/ripple/ripple-dev-portal" title="GitHub">Site Source</a></li>
|
||||
</ul><!-- /#dev-menu -->
|
||||
</div><!-- /.subnav .container -->
|
||||
</div><!-- /.subnav -->
|
||||
</header>
|
||||
|
||||
|
||||
<div class="wrap container" role="document">
|
||||
<aside class="sidebar" role="complementary">
|
||||
<div class="dev_nav_wrapper">
|
||||
<div id="cont">
|
||||
<h5>In this category:</h5>
|
||||
<ul class="dev_nav_sidebar">
|
||||
<li class="level-1"><a href="index.html">Category: Features</a></li>
|
||||
<li class="level-2"><a href="concept-accounts.html">Accounts</a></li>
|
||||
<li class="level-2"><a href="concept-amendments.html">Amendments</a></li>
|
||||
<li class="level-2"><a href="concept-consensus.html">Consensus Process</a></li>
|
||||
<li class="level-2"><a href="concept-reaching-consensus.html">Reaching Consensus in the XRP Ledger</a></li>
|
||||
<li class="level-2"><a href="concept-fee-voting.html">Fee Voting</a></li>
|
||||
<li class="level-2"><a href="concept-fees.html">Fees (Disambiguation)</a></li>
|
||||
<li class="level-2"><a href="concept-freeze.html">Freeze</a></li>
|
||||
<li class="level-2"><a href="concept-partial-payments.html">Partial Payments</a></li>
|
||||
<li class="level-2"><a href="concept-paths.html">Paths</a></li>
|
||||
<li class="level-2"><a href="concept-reserves.html">Reserves</a></li>
|
||||
<li class="level-2"><a href="concept-stand-alone-mode.html">Stand-Alone Mode</a></li>
|
||||
<li class="level-2"><a href="concept-transaction-cost.html">Transaction Cost</a></li>
|
||||
<li class="level-2"><a href="concept-transfer-fees.html">Transfer Fees</a></li>
|
||||
<li class="level-2"><a href="concept-noripple.html">Understanding the NoRipple flag</a></li>
|
||||
</ul>
|
||||
<hr />
|
||||
<h5>In this page:</h5>
|
||||
<ul class="dev_nav_sidebar" id="dactyl_toc_sidebar">
|
||||
<li class="level-1"><a href="#freeze-features">Freeze Features</a></li>
|
||||
<li class="level-2"><a href="#individual-freeze">Individual Freeze</a></li>
|
||||
<li class="level-2"><a href="#global-freeze">Global Freeze</a></li>
|
||||
<li class="level-2"><a href="#no-freeze">No Freeze</a></li>
|
||||
<li class="level-1"><a href="#technical-details">Technical Details</a></li>
|
||||
<li class="level-2"><a href="#enabling-or-disabling-individual-freeze">Enabling or Disabling Individual Freeze</a></li>
|
||||
<li class="level-3"><a href="#using-rippled">Using rippled</a></li>
|
||||
<li class="level-3"><a href="#using-rippleapi">Using RippleAPI</a></li>
|
||||
<li class="level-2"><a href="#enabling-or-disabling-global-freeze">Enabling or Disabling Global Freeze</a></li>
|
||||
<li class="level-3"><a href="#using-rippled-1">Using rippled</a></li>
|
||||
<li class="level-3"><a href="#using-rippleapi-1">Using RippleAPI</a></li>
|
||||
<li class="level-2"><a href="#enabling-no-freeze">Enabling No Freeze</a></li>
|
||||
<li class="level-3"><a href="#using-rippled-2">Using rippled</a></li>
|
||||
<li class="level-3"><a href="#using-rippleapi-2">Using RippleAPI</a></li>
|
||||
<li class="level-2"><a href="#checking-for-individual-freeze">Checking for Individual Freeze</a></li>
|
||||
<li class="level-3"><a href="#using-rippled-3">Using rippled</a></li>
|
||||
<li class="level-3"><a href="#using-rippleapi-3">Using RippleAPI</a></li>
|
||||
<li class="level-2"><a href="#checking-for-global-freeze-and-no-freeze">Checking for Global Freeze and No Freeze</a></li>
|
||||
<li class="level-3"><a href="#using-rippled-4">Using rippled</a></li>
|
||||
<li class="level-3"><a href="#using-rippleapi-4">Using RippleAPI</a></li>
|
||||
<li class="level-1"><a href="#see-also">See Also</a></li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
<main class="main" role="main">
|
||||
<div class='content'>
|
||||
<h1 id="freeze-features">Freeze Features</h1>
|
||||
<p>The XRP Ledger gives addresses the ability to freeze non-XRP balances, which can be useful to meet regulatory requirements, or while investigating suspicious activity. There are three settings related to freezes:</p>
|
||||
<ul>
|
||||
<li><a href="#individual-freeze"><strong>Individual Freeze</strong></a> - Freeze one counterparty.</li>
|
||||
<li><a href="#global-freeze"><strong>Global Freeze</strong></a> - Freeze all counterparties.</li>
|
||||
<li><a href="#no-freeze"><strong>No Freeze</strong></a> - Permanently give up the ability to freeze individual counterparties, as well as the ability to end a global freeze.</li>
|
||||
</ul>
|
||||
<p>Because no party has a privileged place in the XRP Ledger, the freeze feature cannot prevent a counterparty from conducting transactions in XRP or funds issued by other counterparties. No one can freeze XRP.</p>
|
||||
<p>All freeze settings can be enacted regardless of whether the balance(s) to be frozen are positive or negative. Either the currency issuer or the currency holder can freeze a trust line; however, the effect of a currency holder freezing an issuer is minimal.</p>
|
||||
<h2 id="individual-freeze">Individual Freeze</h2>
|
||||
<p>The <strong>Individual Freeze</strong> feature is a setting on a trust line. When an issuing address enables the Individual Freeze setting, the following rules apply:</p>
|
||||
<ul>
|
||||
<li>Payments can still occur directly between the two parties of the frozen trust line.</li>
|
||||
<li>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 issuances directly to the issuer.</li>
|
||||
<li>The counterparty can still receive payments from others on the frozen trust line.</li>
|
||||
<li>The counterparty's offers to sell the currency issued on the frozen trust line are <a href="reference-transaction-format.html#lifecycle-of-an-offer">considered unfunded</a>.</li>
|
||||
</ul>
|
||||
<p>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 operates 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.)</p>
|
||||
<p>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 addresses, including <a href="concept-issuing-and-operational-addresses.html">operational addresses</a>, from sending that financial institution's issuances to the individual address. This type of individual freeze has no effect on offers.</p>
|
||||
<p>The Individual Freeze applies to a single currency only. To freeze multiple currencies with a particular counterparty, the address must enable Individual Freeze on the trust lines for each currency individually.</p>
|
||||
<p>An address cannot enable the Individual Freeze setting if it has enabled the <a href="#no-freeze">No Freeze</a> setting.</p>
|
||||
<h2 id="global-freeze">Global Freeze</h2>
|
||||
<p>The <strong>Global Freeze</strong> feature is a setting on an address. When an issuing address enables the Global Freeze feature, the following rules apply:</p>
|
||||
<ul>
|
||||
<li>All counterparties of the frozen issuing address can no longer decrease the balances in their trust lines to the frozen address, except in direct payments to the issuer. (This also affects any <a href="concept-issuing-and-operational-addresses.html">operational addresses</a>.)</li>
|
||||
<li>Counterparties of the frozen issuing address can still send and receive payments directly to and from the issuing address.</li>
|
||||
<li>All offers to sell currencies issued by the frozen address are <a href="reference-transaction-format.html#lifecycle-of-an-offer">considered unfunded</a>.</li>
|
||||
</ul>
|
||||
<p>It can be useful to enable Global Freeze on a financial institution's <a href="concept-issuing-and-operational-addresses.html">issuing address</a> if the secret key to an operational address 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, a financial institution should also suspend activities in its connectors to outside systems.</p>
|
||||
<p>It can also be useful to enable Global Freeze if a financial institution intends to migrate to a new <a href="concept-issuing-and-operational-addresses.html">issuing address</a>, 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.</p>
|
||||
<p>Global Freeze applies to <em>all</em> currencies issued and held by the address. You cannot enable Global Freeze for only one currency. If you want to have the ability to freeze some currencies and not others, you should use different addresses for each currency.</p>
|
||||
<p>An address can always enable the Global Freeze setting. However, if the address has enabled the <a href="#no-freeze">No Freeze</a> setting, it can never <em>disable</em> Global Freeze.</p>
|
||||
<h2 id="no-freeze">No Freeze</h2>
|
||||
<p>The <strong>No Freeze</strong> feature is a setting on an address that permanently gives up the ability to freeze counterparties. A business can use this feature to treat its issued funds as "more like physical money" in the sense that the business cannot interfere with customers trading it among themselves. The NoFreeze setting has two effects:</p>
|
||||
<ul>
|
||||
<li>The issuing address can no longer enable Individual Freeze on trust lines to any counterparty.</li>
|
||||
<li>The issuing address can still enable Global Freeze to enact a global freeze, but the address cannot <em>disable</em> Global Freeze.</li>
|
||||
</ul>
|
||||
<p>The XRP Ledger cannot force a financial institution to honor the obligations that its issued funds represent, so giving up the ability to enable a Global Freeze cannot protect customers. However, giving up the ability to <em>disable</em> a Global Freeze ensures that the Global Freeze feature is not used unfairly against some customers.</p>
|
||||
<p>The No Freeze setting applies to all currencies issued to and from an address. If you want to be able to freeze some currencies but not others, you should use different addresses for each currency.</p>
|
||||
<p>You can only enable the No Freeze setting with a transaction signed by your address's master key secret. You cannot use a <a href="reference-transaction-format.html#setregularkey">Regular Key</a> or a <a href="reference-transaction-format.html#multi-signing">multi-signed transaction</a> to enable No Freeze.</p>
|
||||
<h1 id="technical-details">Technical Details</h1>
|
||||
<h2 id="enabling-or-disabling-individual-freeze">Enabling or Disabling Individual Freeze</h2>
|
||||
<h3 id="using-rippled">Using <code>rippled</code></h3>
|
||||
<p>To enable or disable Individual Freeze on a specific trust line, send a <code>TrustSet</code> transaction. Use the <a href="reference-transaction-format.html#trustset-flags"><code>tfSetFreeze</code> flag</a> to enable a freeze, and the <code>tfClearFreeze</code> flag to disable it. The fields of the transaction should be as follows:</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Field</th>
|
||||
<th>Value</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Account</td>
|
||||
<td>String</td>
|
||||
<td>The XRP Ledger address to enable or disable the freeze.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>TransactionType</td>
|
||||
<td>String</td>
|
||||
<td><code>TrustSet</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>LimitAmount</td>
|
||||
<td>Object</td>
|
||||
<td>Object defining the trust line to freeze.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>LimitAmount.currency</td>
|
||||
<td>String</td>
|
||||
<td>Currency of the trust line</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>LimitAmount.issuer</td>
|
||||
<td>String</td>
|
||||
<td>The XRP Ledger address of the counterparty to freeze</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>LimitAmount.value</td>
|
||||
<td>String</td>
|
||||
<td>The amount of currency you trust this counterparty to issue to you, as a quoted number. From the perspective of a financial institution, this is typically <code>"0"</code>.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Flags</td>
|
||||
<td>Number</td>
|
||||
<td>To enable a freeze, use a value with the bit <code>0x00100000</code> (tfSetFreeze) enabled. To disable a freeze, use a value with the bit <code>0x00200000</code> (tfClearFreeze) enabled instead.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>Set the <code>Fee</code>, <code>Sequence</code>, and <code>LastLedgerSequence</code> parameters <a href="reference-transaction-format.html#signing-and-submitting-transactions">in the typical way</a>.</p>
|
||||
<p>Example of submitting a TrustSet transaction to enable an individual freeze using the <a href="reference-rippled.html#websocket-api">WebSocket API</a>:</p>
|
||||
<pre><code>{
|
||||
"id": 12,
|
||||
"command": "submit",
|
||||
"tx_json": {
|
||||
"TransactionType": "TrustSet",
|
||||
"Account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"Fee": "12000",
|
||||
"Flags": 1048576,
|
||||
"LastLedgerSequence": 18103014,
|
||||
"LimitAmount": {
|
||||
"currency": "USD",
|
||||
"issuer": "rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW",
|
||||
"value": "110"
|
||||
},
|
||||
"Sequence": 340
|
||||
},
|
||||
"secret": "s████████████████████████████",
|
||||
"offline": false,
|
||||
"fee_mult_max": 1000
|
||||
}
|
||||
</code></pre>
|
||||
<p class="devportal-callout caution"><strong>Caution:</strong> Never send your secret key to an untrusted server or over an insecure channel.</p>
|
||||
<h3 id="using-rippleapi">Using RippleAPI</h3>
|
||||
<p>To enable or disable Individual Freeze on a specific trust line, prepare a <em>Trustline</em> transaction using the <a href="reference-rippleapi.html#preparetrustline">prepareTrustline</a> method. The fields of the <code>trustline</code> parameter should be set as follows:</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Field</th>
|
||||
<th>Value</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>currency</td>
|
||||
<td>String</td>
|
||||
<td>The <a href="reference-rippleapi.html#currency">currency</a> of the trust line to freeze</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>counterparty</td>
|
||||
<td>String</td>
|
||||
<td>The <a href="reference-rippleapi.html#address">XRP Ledger address</a> of the counterparty</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>limit</td>
|
||||
<td>String</td>
|
||||
<td>The amount of currency you trust this counterparty to issue to you, as a quoted number. From the perspective of a financial institution, this is typically <code>"0"</code>.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>frozen</td>
|
||||
<td>Boolean</td>
|
||||
<td><code>true</code> to enable Individual Freeze on this trust line. <code>false</code> to disable Individual Freeze.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>The rest of the <a href="reference-rippleapi.html#transaction-flow">transaction flow</a> is the same as any other transaction.</p>
|
||||
<p>Example JavaScript (ECMAScript 6) code to enable Individual Freeze on a trust line:</p>
|
||||
<pre><code class="js">const {RippleAPI} = require('ripple-lib');
|
||||
|
||||
const api = new RippleAPI({
|
||||
server: 'wss://s1.ripple.com' // Public rippled server
|
||||
});
|
||||
api.on('error', (errorCode, errorMessage) => {
|
||||
console.log(errorCode + ': ' + errorMessage);
|
||||
});
|
||||
|
||||
const issuing_address = 'rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn';
|
||||
const issuing_secret = 's████████████████████████████';
|
||||
// Best practice: get your secret from an encrypted
|
||||
// config file instead
|
||||
const address_to_freeze = 'rUpy3eEg8rqjqfUoLeBnZkscbKbFsKXC3v';
|
||||
const currency_to_freeze = 'USD';
|
||||
|
||||
api.connect().then(() => {
|
||||
|
||||
// Look up current state of trust line
|
||||
const options = {counterparty: address_to_freeze,
|
||||
currency: currency_to_freeze};
|
||||
console.log('looking up', currency_to_freeze, 'trust line from',
|
||||
issuing_address, 'to', address_to_freeze);
|
||||
return api.getTrustlines(issuing_address, options);
|
||||
|
||||
}).then(data => {
|
||||
|
||||
// Prepare a trustline transaction to enable freeze
|
||||
let trustline = {};
|
||||
if (data.length !== 1) {
|
||||
console.log('trustline not found, making a default one');
|
||||
trustline = {
|
||||
currency: currency_to_freeze,
|
||||
counterparty: address_to_freeze,
|
||||
limit: 0
|
||||
};
|
||||
} else {
|
||||
trustline = data[0].specification;
|
||||
console.log('trustline found. previous state:', trustline);
|
||||
}
|
||||
|
||||
trustline.frozen = true;
|
||||
|
||||
console.log('preparing trustline transaction for line:', trustline);
|
||||
return api.prepareTrustline(issuing_address, trustline);
|
||||
|
||||
}).then(prepared_tx => {
|
||||
|
||||
// Sign and submit the trustline transaction
|
||||
console.log('signing tx:', prepared_tx.txJSON);
|
||||
const signed1 = api.sign(prepared_tx.txJSON, issuing_secret);
|
||||
console.log('submitting tx:', signed1.id);
|
||||
|
||||
return api.submit(signed1.signedTransaction);
|
||||
}).then(() => {
|
||||
return api.disconnect();
|
||||
}).catch(console.error);
|
||||
</code></pre>
|
||||
<h2 id="enabling-or-disabling-global-freeze">Enabling or Disabling Global Freeze</h2>
|
||||
<h3 id="using-rippled-1">Using <code>rippled</code></h3>
|
||||
<p>To enable Global Freeze on an address, send an <code>AccountSet</code> transaction with the <a href="reference-transaction-format.html#accountset-flags">asfGlobalFreeze flag value</a> in the <code>SetFlag</code> field. To disable Global Freeze, put the asfGlobalFreeze flag value in the <code>ClearFlag</code> field instead.</p>
|
||||
<p>Example of submitting an AccountSet transaction to enable Global Freeze using the <a href="reference-rippled.html#websocket-api">WebSocket API</a>:</p>
|
||||
<pre><code>{
|
||||
"id": 12,
|
||||
"command": "submit",
|
||||
"tx_json": {
|
||||
"TransactionType": "AccountSet",
|
||||
"Account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"Fee": "12000",
|
||||
"Flags": 0,
|
||||
"SetFlag": 7,
|
||||
"LastLedgerSequence": 18122753,
|
||||
"Sequence": 349
|
||||
},
|
||||
"secret": "s████████████████████████████",
|
||||
"offline": false,
|
||||
"fee_mult_max": 1000
|
||||
}
|
||||
</code></pre>
|
||||
<p class="devportal-callout caution"><strong>Caution:</strong> Never send your secret key to an untrusted server or over an insecure channel.</p>
|
||||
<h3 id="using-rippleapi-1">Using RippleAPI</h3>
|
||||
<p>To enable or disable Global Freeze on an address, prepare a <strong>Settings</strong> transaction using the <a href="reference-rippleapi.html#preparesettings">prepareSettings</a> method. The <code>settings</code> parameter should be an object set as follows:</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Field</th>
|
||||
<th>Value</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>globalFreeze</td>
|
||||
<td>Boolean</td>
|
||||
<td><code>true</code> to enable a Global Freeze on this address. <code>false</code> to disable Global Freeze.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>The rest of the <a href="reference-rippleapi.html#transaction-flow">transaction flow</a> is the same as any other transaction.</p>
|
||||
<p>Example JavaScript (ECMAScript 6) code to enable Global Freeze on an address:</p>
|
||||
<pre><code class="js">const {RippleAPI} = require('ripple-lib');
|
||||
|
||||
const api = new RippleAPI({
|
||||
server: 'wss://s1.ripple.com' // Public rippled server
|
||||
});
|
||||
api.on('error', (errorCode, errorMessage) => {
|
||||
console.log(errorCode + ': ' + errorMessage);
|
||||
});
|
||||
|
||||
const issuing_address = 'rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn';
|
||||
const issuing_secret = 's████████████████████████████';
|
||||
// Best practice: get your secret from an encrypted
|
||||
// config file instead
|
||||
|
||||
api.connect().then(() => {
|
||||
|
||||
// Prepare a settings transaction to enable global freeze
|
||||
const settings = {
|
||||
'globalFreeze': true
|
||||
};
|
||||
|
||||
console.log('preparing settings transaction for account:',
|
||||
issuing_address);
|
||||
return api.prepareSettings(issuing_address, settings);
|
||||
|
||||
}).then(prepared_tx => {
|
||||
|
||||
// Sign and submit the settings transaction
|
||||
console.log('signing tx:', prepared_tx.txJSON);
|
||||
const signed1 = api.sign(prepared_tx.txJSON, issuing_secret);
|
||||
console.log('submitting tx:', signed1.id);
|
||||
|
||||
return api.submit(signed1.signedTransaction);
|
||||
|
||||
}).then(() => {
|
||||
return api.disconnect();
|
||||
}).catch(console.error);
|
||||
</code></pre>
|
||||
<h2 id="enabling-no-freeze">Enabling No Freeze</h2>
|
||||
<h3 id="using-rippled-2">Using <code>rippled</code></h3>
|
||||
<p>To enable No Freeze on an address, send an <code>AccountSet</code> transaction with the <a href="reference-transaction-format.html#accountset-flags">asfNoFreeze flag value</a> in the <code>SetFlag</code> field. You must sign this transaction using the master key. Once enabled, you cannot disable No Freeze.</p>
|
||||
<p>Example of submitting an AccountSet transaction to enable No Freeze using the <a href="reference-rippled.html#websocket-api">WebSocket API</a>:</p>
|
||||
<p>WebSocket request:</p>
|
||||
<pre><code>{
|
||||
"id": 12,
|
||||
"command": "submit",
|
||||
"tx_json": {
|
||||
"TransactionType": "AccountSet",
|
||||
"Account": "raKEEVSGnKSD9Zyvxu4z6Pqpm4ABH8FS6n",
|
||||
"Fee": "12000",
|
||||
"Flags": 0,
|
||||
"SetFlag": 6,
|
||||
"LastLedgerSequence": 18124917,
|
||||
"Sequence": 4
|
||||
},
|
||||
"secret": "s████████████████████████████",
|
||||
"offline": false,
|
||||
"fee_mult_max": 1000
|
||||
}
|
||||
</code></pre>
|
||||
<p class="devportal-callout caution"><strong>Caution:</strong> Never send your secret key to an untrusted server or over an insecure channel.</p>
|
||||
<h3 id="using-rippleapi-2">Using RippleAPI</h3>
|
||||
<p>To enable No Freeze on an address, prepare a <strong>Settings</strong> transaction using the <a href="reference-rippleapi.html#preparesettings">prepareSettings</a> method. Once enabled, you cannot disable No Freeze. The <code>settings</code> parameter should be an object set as follows:</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Field</th>
|
||||
<th>Value</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>noFreeze</td>
|
||||
<td>Boolean</td>
|
||||
<td><code>true</code></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>You must <a href="reference-rippleapi.html#sign">sign</a> this transaction using the master key. The rest of the <a href="reference-rippleapi.html#transaction-flow">transaction flow</a> is the same as any other transaction.</p>
|
||||
<p>Example JavaScript (ECMAScript 6) code to enable No Freeze on an address:</p>
|
||||
<pre><code class="js">const {RippleAPI} = require('ripple-lib');
|
||||
|
||||
const api = new RippleAPI({
|
||||
server: 'wss://s1.ripple.com' // Public rippled server
|
||||
});
|
||||
api.on('error', (errorCode, errorMessage) => {
|
||||
console.log(errorCode + ': ' + errorMessage);
|
||||
});
|
||||
|
||||
const issuing_address = 'rUpy3eEg8rqjqfUoLeBnZkscbKbFsKXC3v';
|
||||
const issuing_secret = 'snnDVkSW3aV6jvMJTPdCiE2Qxv1RW';
|
||||
// Best practice: get your secret from an encrypted
|
||||
// config file instead
|
||||
|
||||
api.connect().then(() => {
|
||||
|
||||
// Prepare a settings transaction to enable no freeze
|
||||
const settings = {
|
||||
'noFreeze': true
|
||||
};
|
||||
|
||||
console.log('preparing settings transaction for account:',
|
||||
issuing_address);
|
||||
return api.prepareSettings(issuing_address, settings);
|
||||
|
||||
}).then(prepared_tx => {
|
||||
|
||||
// Sign and submit the settings transaction
|
||||
console.log('signing tx:', prepared_tx.txJSON);
|
||||
const signed1 = api.sign(prepared_tx.txJSON, issuing_secret);
|
||||
console.log('submitting tx:', signed1.id);
|
||||
|
||||
return api.submit(signed1.signedTransaction);
|
||||
}).then(() => {
|
||||
return api.disconnect();
|
||||
}).catch(console.error);
|
||||
</code></pre>
|
||||
<h2 id="checking-for-individual-freeze">Checking for Individual Freeze</h2>
|
||||
<h3 id="using-rippled-3">Using <code>rippled</code></h3>
|
||||
<p>To see if a trust line has an Individual Freeze enabled, use the <a href="reference-rippled.html#account-lines"><code>account_lines</code> method</a> with the following parameters:</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Field</th>
|
||||
<th>Value</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>account</td>
|
||||
<td>String</td>
|
||||
<td>The XRP Ledger address of the issuer</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>peer</td>
|
||||
<td>String</td>
|
||||
<td>The XRP Ledger address of the counterparty</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>ledger_index</td>
|
||||
<td>String</td>
|
||||
<td>Use <code>validated</code> to get the most recently validated information.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>The response contains an array of trust lines, for each currency in which the issuing address and the counterparty are linked. Look for the following fields in each trust line object:</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Field</th>
|
||||
<th>Value</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>freeze</td>
|
||||
<td>Boolean</td>
|
||||
<td>(May be omitted) <code>true</code> if the issuing address has frozen this trust line. If omitted, that is the same as <code>false</code>.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>freeze_peer</td>
|
||||
<td>Boolean</td>
|
||||
<td>(May be omitted) <code>true</code> if the counterparty has frozen this trust line. If omitted, that is the same as <code>false</code>.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>Example WebSocket request to check for individual freeze:</p>
|
||||
<pre><code>{
|
||||
"id": 15,
|
||||
"command": "account_lines",
|
||||
"account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"ledger": "validated",
|
||||
"peer": "rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW"
|
||||
}
|
||||
</code></pre>
|
||||
<p>Example WebSocket response:</p>
|
||||
<pre><code>{
|
||||
"id": 15,
|
||||
"status": "success",
|
||||
"type": "response",
|
||||
"result": {
|
||||
"account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"lines": [
|
||||
{
|
||||
"account": "rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW",
|
||||
"balance": "10",
|
||||
"currency": "USD",
|
||||
"freeze": true,
|
||||
"limit": "110",
|
||||
"limit_peer": "0",
|
||||
"peer_authorized": true,
|
||||
"quality_in": 0,
|
||||
"quality_out": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
</code></pre>
|
||||
<p>The field <code>"freeze": true</code> indicates that rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn has enabled Individual Freeze on the USD trust line to rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW. The lack of a field <code>"freeze_peer": true</code> indicates that the counterparty has <em>not</em> frozen the trust line.</p>
|
||||
<h3 id="using-rippleapi-3">Using RippleAPI</h3>
|
||||
<p>To see if a trust line has an Individual Freeze enabled, use the <a href="reference-rippleapi.html#gettrustlines"><code>getTrustlines</code> method</a> with the following parameters:</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Field</th>
|
||||
<th>Value</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>address</td>
|
||||
<td>String</td>
|
||||
<td>The XRP Ledger address of the issuer</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>options.counterparty</td>
|
||||
<td>String</td>
|
||||
<td>The XRP Ledger address of the counterparty</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>The response contains an array of trust lines, for each currency in which the issuing address and the counterparty are linked. Look for the following fields in each trust line object:</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Field</th>
|
||||
<th>Value</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>specification.frozen</td>
|
||||
<td>Boolean</td>
|
||||
<td>(May be omitted) <code>true</code> if the issuing address has frozen the trust line.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>counterparty.frozen</td>
|
||||
<td>Boolean</td>
|
||||
<td>(May be omitted) <code>true</code> if the counterparty has frozen the trust line.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>Example JavaScript (ECMAScript 6) code to check whether a trust line is frozen:</p>
|
||||
<pre><code class="js">const {RippleAPI} = require('ripple-lib');
|
||||
|
||||
const api = new RippleAPI({
|
||||
server: 'wss://s1.ripple.com' // Public rippled server
|
||||
});
|
||||
api.on('error', (errorCode, errorMessage) => {
|
||||
console.log(errorCode + ': ' + errorMessage);
|
||||
});
|
||||
|
||||
const my_address = 'rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn';
|
||||
const counterparty_address = 'rUpy3eEg8rqjqfUoLeBnZkscbKbFsKXC3v';
|
||||
const frozen_currency = 'USD';
|
||||
|
||||
api.connect().then(() => {
|
||||
|
||||
// Look up current state of trust line
|
||||
const options = {counterparty: counterparty_address,
|
||||
currency: frozen_currency};
|
||||
console.log('looking up', frozen_currency, 'trust line from',
|
||||
my_address, 'to', counterparty_address);
|
||||
return api.getTrustlines(my_address, options);
|
||||
|
||||
}).then(data => {
|
||||
|
||||
if (data.length !== 1) {
|
||||
throw 'should only be 1 trust line per counterparty+currency pair';
|
||||
}
|
||||
|
||||
const trustline = data[0];
|
||||
console.log('Trust line frozen from our side?',
|
||||
trustline.specification.frozen === true);
|
||||
console.log('Trust line frozen from counterparty\'s side?',
|
||||
trustline.counterparty.frozen === true);
|
||||
|
||||
}).then(() => {
|
||||
return api.disconnect();
|
||||
}).catch(console.error);
|
||||
</code></pre>
|
||||
<h2 id="checking-for-global-freeze-and-no-freeze">Checking for Global Freeze and No Freeze</h2>
|
||||
<h3 id="using-rippled-4">Using <code>rippled</code></h3>
|
||||
<p>To see if an address has enabled Global Freeze, No Freeze, or both, use the <a href="reference-rippled.html#account-lines"><code>account_info</code> method</a> with the following parameters:</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Field</th>
|
||||
<th>Value</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>account</td>
|
||||
<td>String</td>
|
||||
<td>The XRP Ledger address of the issuing address</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>ledger_index</td>
|
||||
<td>String</td>
|
||||
<td>Use <code>validated</code> to get the most recently validated information.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>Check the value of the <code>account_data.Flags</code> field of the response using the <a href="https://en.wikipedia.org/wiki/Bitwise_operation#AND">bitwise-AND</a> operator:</p>
|
||||
<ul>
|
||||
<li>If <code>Flags</code> AND <code>0x00400000</code> (<a href="reference-ledger-format.html#accountroot-flags">lsfGlobalFreeze</a>) is <em>nonzero</em>: Global Freeze is enabled.</li>
|
||||
<li>If <code>Flags</code> AND <code>0x00200000</code> (<a href="reference-ledger-format.html#accountroot-flags">lsfNoFreeze</a>) is <em>nonzero</em>: No Freeze is enabled.</li>
|
||||
</ul>
|
||||
<p>Example WebSocket request:</p>
|
||||
<pre><code>{
|
||||
"id": 1,
|
||||
"command": "account_info",
|
||||
"account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"ledger_index": "validated"
|
||||
}
|
||||
</code></pre>
|
||||
<p>WebSocket response:</p>
|
||||
<pre><code>{
|
||||
"id": 4,
|
||||
"status": "success",
|
||||
"type": "response",
|
||||
"result": {
|
||||
"account_data": {
|
||||
"Account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"AccountTxnID": "41320138CA9837B34E82B3B3D6FB1E581D5DE2F0A67B3D62B5B8A8C9C8D970D0",
|
||||
"Balance": "100258663",
|
||||
"Domain": "6D64756F31332E636F6D",
|
||||
"EmailHash": "98B4375E1D753E5B91627516F6D70977",
|
||||
"Flags": 12582912,
|
||||
"LedgerEntryType": "AccountRoot",
|
||||
"MessageKey": "0000000000000000000000070000000300",
|
||||
"OwnerCount": 4,
|
||||
"PreviousTxnID": "41320138CA9837B34E82B3B3D6FB1E581D5DE2F0A67B3D62B5B8A8C9C8D970D0",
|
||||
"PreviousTxnLgrSeq": 18123095,
|
||||
"Sequence": 352,
|
||||
"TransferRate": 1004999999,
|
||||
"index": "13F1A95D7AAB7108D5CE7EEAF504B2894B8C674E6D68499076441C4837282BF8",
|
||||
"urlgravatar": "http://www.gravatar.com/avatar/98b4375e1d753e5b91627516f6d70977"
|
||||
},
|
||||
"ledger_hash": "A777B05A293A73E511669B8A4A45A298FF89AD9C9394430023008DB4A6E7FDD5",
|
||||
"ledger_index": 18123249,
|
||||
"validated": true
|
||||
}
|
||||
}
|
||||
</code></pre>
|
||||
<p>In the above example, the <code>Flags</code> value is 12582912. This indicates that has the following flags enabled: lsfGlobalFreeze, lsfDefaultRipple, as demonstrated by the following JavaScript code:</p>
|
||||
<pre><code class="js">var lsfGlobalFreeze = 0x00400000;
|
||||
var lsfNoFreeze = 0x00200000;
|
||||
|
||||
var currentFlags = 12582912;
|
||||
|
||||
console.log(currentFlags & lsfGlobalFreeze); //4194304
|
||||
//therefore, Global Freeze is enabled
|
||||
|
||||
console.log(currentFlags & lsfNoFreeze); //0
|
||||
//therefore, No Freeze is not enabled
|
||||
</code></pre>
|
||||
<h3 id="using-rippleapi-4">Using RippleAPI</h3>
|
||||
<p>To see if an address has enabled Global Freeze, No Freeze, or both, use the <a href="reference-rippleapi.html#getsettings"><code>getSettings</code> method</a> with the following parameters:</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Field</th>
|
||||
<th>Value</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>address</td>
|
||||
<td>String</td>
|
||||
<td>The XRP Ledger address of the issuing address</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>Look for the following values in the response object:</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Field</th>
|
||||
<th>Value</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>noFreeze</td>
|
||||
<td>Boolean</td>
|
||||
<td>(May be omitted) <code>true</code> if No Freeze is enabled.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>globalFreeze</td>
|
||||
<td>Boolean</td>
|
||||
<td>(May be omitted) <code>true</code> if Global Freeze is enabled.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>Example JavaScript (ECMAScript 6) code to check whether an address has Global Freeze or No Freeze enabled:</p>
|
||||
<pre><code class="js">const {RippleAPI} = require('ripple-lib');
|
||||
|
||||
const api = new RippleAPI({
|
||||
server: 'wss://s1.ripple.com' // Public rippled server
|
||||
});
|
||||
api.on('error', (errorCode, errorMessage) => {
|
||||
console.log(errorCode + ': ' + errorMessage);
|
||||
});
|
||||
|
||||
const my_address = 'rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn';
|
||||
|
||||
api.connect().then(() => {
|
||||
// Look up settings object
|
||||
return api.getSettings(my_address);
|
||||
}).then(settings => {
|
||||
console.log('Got settings for address', my_address);
|
||||
console.log('Global Freeze enabled?',
|
||||
(settings.globalFreeze === true));
|
||||
console.log('No Freeze enabled?', (settings.noFreeze === true));
|
||||
|
||||
}).then(() => {
|
||||
return api.disconnect();
|
||||
}).catch(console.error);
|
||||
</code></pre>
|
||||
<h1 id="see-also">See Also</h1>
|
||||
<ul>
|
||||
<li><a href="https://ripple.com/files/GB-2014-02.pdf">GB-2014-02 New Feature: Balance Freeze</a></li>
|
||||
<li><a href="https://github.com/ripple/ripple-dev-portal/tree/gh-pages/content/code_samples/freeze">Freeze Code Samples</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<footer class="content-info" role="contentinfo">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-sm-12 absolute_bottom_footer">
|
||||
<div class="col-sm-8">
|
||||
<span>© 2013 - 2017 Ripple Labs, Inc. All Rights Reserved.</span>
|
||||
<span><a href="/terms-of-use/">Terms</a></span>
|
||||
<span><a href="/privacy-policy/">Privacy</a></span>
|
||||
</div>
|
||||
</div><!-- /.absolute_bottom_footer -->
|
||||
|
||||
</div><!-- /.row -->
|
||||
</div><!-- /.container -->
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,213 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<meta name="viewport" content="width=device-width">
|
||||
|
||||
<title>Issuing and Operational Addresses - Ripple Developer Portal</title>
|
||||
|
||||
<!-- favicon -->
|
||||
<link rel="icon" href="favicon.ico" type="image/x-icon">
|
||||
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon">
|
||||
|
||||
<!-- jQuery -->
|
||||
<script src="assets/vendor/jquery-1.11.1.min.js"></script>
|
||||
|
||||
<!-- Custom Stylesheets. ripple.css includes bootstrap, font stuff -->
|
||||
<link href="assets/css/ripple.css" rel="stylesheet" />
|
||||
<link href="assets/css/devportal.css" rel="stylesheet" />
|
||||
|
||||
<!-- Bootstrap JS -->
|
||||
<script src="assets/vendor/bootstrap.min.js"></script>
|
||||
|
||||
|
||||
<!-- syntax highlighting -->
|
||||
<link rel="stylesheet" href="assets/vendor/docco.min.css" />
|
||||
<script src="assets/vendor/highlight.min.js"></script>
|
||||
|
||||
<!-- syntax selection js -->
|
||||
<script src="assets/js/multicodetab.js"></script>
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
$(".multicode").minitabs();
|
||||
hljs.initHighlighting();
|
||||
make_code_expandable();
|
||||
});
|
||||
</script>
|
||||
|
||||
<script src="assets/js/expandcode.js"></script>
|
||||
<script src="assets/js/fixsidebarscroll.js"></script>
|
||||
|
||||
<!-- fontawesome icons -->
|
||||
<link rel="stylesheet" href="assets/vendor/fontawesome/css/font-awesome.min.css" />
|
||||
|
||||
</head>
|
||||
|
||||
<body class="page page-template page-template-template-dev-portal page-template-template-dev-portal-php sidebar-primary wpb-js-composer js-comp-ver-3.6.2 vc_responsive">
|
||||
<header role="banner" class="banner navbar navbar-default navbar-fixed-top initial_header">
|
||||
<div class="container">
|
||||
<div class="navbar-header">
|
||||
<a href="index.html" class="navbar-brand"><img src="assets/img/ripple-logo-color.png" class="logo"></a>
|
||||
</div><!-- /.navbar-header -->
|
||||
<div class="nav">
|
||||
<div class="draft-warning">DRAFT PAGE</div>
|
||||
</div><!-- /.nav -->
|
||||
|
||||
</div><!-- /.container -->
|
||||
|
||||
<div class="subnav dev_nav">
|
||||
<div class="container">
|
||||
<ul id="menu-dev-menu" class="menu">
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">References <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="reference-rippleapi.html">RippleAPI</a></li>
|
||||
<li><a href="reference-rippled.html">rippled</a></li>
|
||||
<li><a href="reference-transaction-format.html">Transaction Format</a></li>
|
||||
<li><a href="reference-ledger-format.html">Ledger Format</a></li>
|
||||
<li><a href="reference-data-api.html">Ripple Data API v2</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorials <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="tutorial-multisign.html">How to Multi-Sign</a></li>
|
||||
<li><a href="tutorial-paychan.html">Payment Channels Tutorial</a></li>
|
||||
<li><a href="concept-issuing-and-operational-addresses.html">Issuing and Operational Addresses</a></li>
|
||||
<li><a href="tutorial-reliable-transaction-submission.html">Reliable Transaction Submission</a></li>
|
||||
<li><a href="tutorial-rippleapi-beginners-guide.html">RippleAPI Beginners Guide</a></li>
|
||||
<li><a href="tutorial-rippled-setup.html">rippled Setup</a></li>
|
||||
<li><a href="tutorial-gateway-guide.html">Gateway Guide</a></li>
|
||||
<li><a href="tutorial-listing-xrp.html">Listing XRP as an Exchange</a></li>
|
||||
<li><a href="tutorial-escrow.html">Escrow Tutorials</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Features <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="concept-accounts.html">Accounts</a></li>
|
||||
<li><a href="concept-amendments.html">Amendments</a></li>
|
||||
<li><a href="concept-consensus.html">Consensus Process</a></li>
|
||||
<li><a href="concept-reaching-consensus.html">Reaching Consensus in the XRP Ledger</a></li>
|
||||
<li><a href="concept-fee-voting.html">Fee Voting</a></li>
|
||||
<li><a href="concept-fees.html">Fees (Disambiguation)</a></li>
|
||||
<li><a href="concept-freeze.html">Freeze</a></li>
|
||||
<li><a href="concept-partial-payments.html">Partial Payments</a></li>
|
||||
<li><a href="concept-paths.html">Paths</a></li>
|
||||
<li><a href="concept-reserves.html">Reserves</a></li>
|
||||
<li><a href="concept-stand-alone-mode.html">Stand-Alone Mode</a></li>
|
||||
<li><a href="concept-transaction-cost.html">Transaction Cost</a></li>
|
||||
<li><a href="concept-transfer-fees.html">Transfer Fees</a></li>
|
||||
<li><a href="concept-noripple.html">Understanding the NoRipple flag</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Gateway Bulletins <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="gb-2015-06.html">GB-2015-06: Corrections to Autobridging</a></li>
|
||||
<li><a href="gb-2015-05.html">GB-2015-05: Historical Ledger Query Migration</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">API Tools <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="ripple-api-tool.html">WebSocket API Tool</a></li>
|
||||
<li><a href="data-api-v2-tool.html">Data API v2 Tool</a></li>
|
||||
<li><a href="tool-jsonrpc.html">rippled JSON-RPC Tool</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li><a href="https://github.com/ripple/ripple-dev-portal" title="GitHub">Site Source</a></li>
|
||||
</ul><!-- /#dev-menu -->
|
||||
</div><!-- /.subnav .container -->
|
||||
</div><!-- /.subnav -->
|
||||
</header>
|
||||
|
||||
|
||||
<div class="wrap container" role="document">
|
||||
<aside class="sidebar" role="complementary">
|
||||
<div class="dev_nav_wrapper">
|
||||
<div id="cont">
|
||||
<h5>In this category:</h5>
|
||||
<ul class="dev_nav_sidebar">
|
||||
<li class="level-1"><a href="index.html">Category: Tutorials</a></li>
|
||||
<li class="level-2"><a href="tutorial-multisign.html">How to Multi-Sign</a></li>
|
||||
<li class="level-2"><a href="tutorial-paychan.html">Payment Channels Tutorial</a></li>
|
||||
<li class="level-2"><a href="concept-issuing-and-operational-addresses.html">Issuing and Operational Addresses</a></li>
|
||||
<li class="level-2"><a href="tutorial-reliable-transaction-submission.html">Reliable Transaction Submission</a></li>
|
||||
<li class="level-2"><a href="tutorial-rippleapi-beginners-guide.html">RippleAPI Beginners Guide</a></li>
|
||||
<li class="level-2"><a href="tutorial-rippled-setup.html">rippled Setup</a></li>
|
||||
<li class="level-2"><a href="tutorial-gateway-guide.html">Gateway Guide</a></li>
|
||||
<li class="level-2"><a href="tutorial-listing-xrp.html">Listing XRP as an Exchange</a></li>
|
||||
<li class="level-2"><a href="tutorial-escrow.html">Escrow Tutorials</a></li>
|
||||
</ul>
|
||||
<hr />
|
||||
<h5>In this page:</h5>
|
||||
<ul class="dev_nav_sidebar" id="dactyl_toc_sidebar">
|
||||
<li class="level-1"><a href="#issuing-and-operational-addresses">Issuing and Operational Addresses</a></li>
|
||||
<li class="level-2"><a href="#funds-lifecycle">Funds Lifecycle</a></li>
|
||||
<li class="level-2"><a href="#issuing-address">Issuing Address</a></li>
|
||||
<li class="level-3"><a href="#issuing-address-compromise">Issuing Address Compromise</a></li>
|
||||
<li class="level-3"><a href="#multiple-issuing-addresses">Multiple Issuing Addresses</a></li>
|
||||
<li class="level-2"><a href="#operational-addresses">Operational Addresses</a></li>
|
||||
<li class="level-3"><a href="#operational-address-compromise">Operational Address Compromise</a></li>
|
||||
<li class="level-2"><a href="#standby-addresses">Standby Addresses</a></li>
|
||||
<li class="level-3"><a href="#standby-address-compromise">Standby Address Compromise</a></li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
<main class="main" role="main">
|
||||
<div class='content'>
|
||||
<h1 id="issuing-and-operational-addresses">Issuing and Operational Addresses</h1>
|
||||
<p>In the XRP Ledger, financial institutions typically use multiple XRP Ledger addresses to minimize the risk associated with a compromised secret key. Ripple strongly recommends the following separation of roles:</p>
|
||||
<ul>
|
||||
<li>One <strong>issuing address</strong>, also known as a "cold wallet." This address is the hub of the financial institution's accounting relationships in the ledger, but sends as few transactions as possible. <!-- STYLE_OVERRIDE: cold wallet, wallet --></li>
|
||||
<li>One or more <strong>operational addresses</strong>, also known as "hot wallets." Automated, internet-connected systems use the secret keys to these addresses to conduct day-to-day business like transfers to customers and partners. <!-- STYLE_OVERRIDE: hot wallet, wallet --></li>
|
||||
<li>Optional <strong>standby addresses</strong>, also known as "warm wallets." Trusted human operators use these addresses to transfer money to the operational addresses. <!-- STYLE_OVERRIDE: warm wallet, wallet --></li>
|
||||
</ul>
|
||||
<h2 id="funds-lifecycle">Funds Lifecycle</h2>
|
||||
<p>All non-XRP currency balances (issuances) in the XRP Ledger are tied to accounting relationships between two XRP Ledger addresses. When a financial institution uses Ripple's recommended separation of roles, funds relating to that institution tend to flow in a cycle.</p>
|
||||
<p><a href="img/funds_flow_diagram.png"><img alt="Diagram: Funds flow from the issuing address to standby addresses, to operational addresses, to customer and partner addresses, and finally back to the issuing address." src="img/funds_flow_diagram.png"/></a></p>
|
||||
<p>When the issuing address sends payments, it creates balances in the accounting relationships in the XRP Ledger. Within the XRP Ledger, users can exchange balances across different accounting relationships, so we use the term <em>issuances</em> to describe any non-XRP balance. Issuances have negative value from the perspective of the issuing address, since they represent obligations. The same issuances have positive value from the perspective of the issuing address's counterparties. When the issuing address receives a payment, this reduces its obligations, erasing the issuances that were sent.</p>
|
||||
<p>The issuing address sends issuances to a standby address, or directly to an operational address. The standby addresses send those issuances to operational addresses. Operational addresses send payments to other counterparties, such as liquidity providers, partners, and other customers. Because all issuances are tied to accounting relationships with the issuing address, payments and exchanges of issuances "ripple through" the issuing address. The payment debits the sender's balance in its accounting relationship with the issuing address and credits the recipient's balance in the recipient's accounting relationship with the issuing address. The XRP Ledger also supports more complicated <a href="concept-paths.html">paths</a> that connect multiple issuers through order books and <a href="concept-noripple.html">liquidity providers who allow their funds to ripple</a>.</p>
|
||||
<h2 id="issuing-address">Issuing Address</h2>
|
||||
<p>The issuing address is like a vault. Partners, customers, and operational addresses create accounting relationships (trust lines) to the issuing address, but this address sends as few transactions as possible. Periodically, a human operator creates and signs a transaction from the issuing address to refill the balances of a standby or operational address. Ideally, the secret key used to sign these transactions should never be accessible from any internet-connected computer.</p>
|
||||
<p>Unlike a vault, the issuing address can receive payments directly from customers and partners. Since all transactions in the XRP Ledger are public, automated systems can monitor for payments to the issuing address without needing a secret key.</p>
|
||||
<h3 id="issuing-address-compromise">Issuing Address Compromise</h3>
|
||||
<p>If a malicious actor learns the secret key behind a institution's issuing address, that actor can create new issuances without limit and trade them in the decentralized exchange. This would make it difficult for the financial institution to distinguish legitimately-obtained issuances and redeem them fairly. If a financial institution loses control of its issuing address, the institution must create a new issuing address, and all users who have accounting relationships with the old issuing address must create new accounting relationships with the new address.</p>
|
||||
<h3 id="multiple-issuing-addresses">Multiple Issuing Addresses</h3>
|
||||
<p>A financial institution can issue more than one currency in the XRP Ledger from a single issuing address. However, there are some settings that apply equally to all currencies issued from an address, including the percentage for <a href="concept-transfer-fees.html">transfer fees</a> and the <a href="concept-freeze.html">global freeze</a> status. If the financial institution wants the flexibility to manage settings differently for each currency, the institution must use a different issuing address for each currency.</p>
|
||||
<h2 id="operational-addresses">Operational Addresses</h2>
|
||||
<p>An operational address is like a cash register. It makes payments on behalf of the institution by transferring issuances to customers and partners. To sign transactions automatically, the secret key for an operational address must be stored on a server that is connected to the internet. (The secret key can be stored encrypted, but the server must decrypt it to sign transactions.) Customers and partners do not, and should not, create accounting relationships with an operational address.</p>
|
||||
<p>Each operational address has a limited balance of issuances. When the balance of an operational address gets low, the financial institution refills it by sending a payment from the issuing address or a standby address.</p>
|
||||
<h3 id="operational-address-compromise">Operational Address Compromise</h3>
|
||||
<p>If a malicious actor learns the secret key behind an operational address, the financial institution can only lose as much currency as that operational address holds. The institution can switch to a new operational address with no action from customers and partners.</p>
|
||||
<h2 id="standby-addresses">Standby Addresses</h2>
|
||||
<p>Another optional step that an institution can take to balance risk and convenience is to use "standby addresses" as an intermediate step between the issuing address and operational addresses. The institution can fund additional XRP Ledger addresses as standby addresses, whose keys are not stored online, but are entrusted to different trusted users.</p>
|
||||
<p>When an operational address is running low on funds, a trusted user can use a standby address to refill the operational address's balance. When a standby addresses run low on funds, the institution can use the issuing address to send more currency to a standby address in a single transaction, and the standby addresses can distribute that currency among themselves if necessary. This improves security of the issuing address, allowing it to make fewer total transactions, without leaving too much money in the control of a single automated system.</p>
|
||||
<p>As with operational addresses, a standby address must have an accounting relationship with the issuing address, and not with customers or partners. All precautions that apply to operational addresses also apply to standby addresses.</p>
|
||||
<h3 id="standby-address-compromise">Standby Address Compromise</h3>
|
||||
<p>If a standby address is compromised, the consequences are like an operational address being compromised. A malicious actor can steal any balances possessed by the standby address, and the financial institution can change to a new standby address with no action from customers and partners.</p>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<footer class="content-info" role="contentinfo">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-sm-12 absolute_bottom_footer">
|
||||
<div class="col-sm-8">
|
||||
<span>© 2013 - 2017 Ripple Labs, Inc. All Rights Reserved.</span>
|
||||
<span><a href="/terms-of-use/">Terms</a></span>
|
||||
<span><a href="/privacy-policy/">Privacy</a></span>
|
||||
</div>
|
||||
</div><!-- /.absolute_bottom_footer -->
|
||||
|
||||
</div><!-- /.row -->
|
||||
</div><!-- /.container -->
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,215 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<meta name="viewport" content="width=device-width">
|
||||
|
||||
<title>Understanding the NoRipple flag - Ripple Developer Portal</title>
|
||||
|
||||
<!-- favicon -->
|
||||
<link rel="icon" href="favicon.ico" type="image/x-icon">
|
||||
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon">
|
||||
|
||||
<!-- jQuery -->
|
||||
<script src="assets/vendor/jquery-1.11.1.min.js"></script>
|
||||
|
||||
<!-- Custom Stylesheets. ripple.css includes bootstrap, font stuff -->
|
||||
<link href="assets/css/ripple.css" rel="stylesheet" />
|
||||
<link href="assets/css/devportal.css" rel="stylesheet" />
|
||||
|
||||
<!-- Bootstrap JS -->
|
||||
<script src="assets/vendor/bootstrap.min.js"></script>
|
||||
|
||||
|
||||
<!-- syntax highlighting -->
|
||||
<link rel="stylesheet" href="assets/vendor/docco.min.css" />
|
||||
<script src="assets/vendor/highlight.min.js"></script>
|
||||
|
||||
<!-- syntax selection js -->
|
||||
<script src="assets/js/multicodetab.js"></script>
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
$(".multicode").minitabs();
|
||||
hljs.initHighlighting();
|
||||
make_code_expandable();
|
||||
});
|
||||
</script>
|
||||
|
||||
<script src="assets/js/expandcode.js"></script>
|
||||
<script src="assets/js/fixsidebarscroll.js"></script>
|
||||
|
||||
<!-- fontawesome icons -->
|
||||
<link rel="stylesheet" href="assets/vendor/fontawesome/css/font-awesome.min.css" />
|
||||
|
||||
</head>
|
||||
|
||||
<body class="page page-template page-template-template-dev-portal page-template-template-dev-portal-php sidebar-primary wpb-js-composer js-comp-ver-3.6.2 vc_responsive">
|
||||
<header role="banner" class="banner navbar navbar-default navbar-fixed-top initial_header">
|
||||
<div class="container">
|
||||
<div class="navbar-header">
|
||||
<a href="index.html" class="navbar-brand"><img src="assets/img/ripple-logo-color.png" class="logo"></a>
|
||||
</div><!-- /.navbar-header -->
|
||||
<div class="nav">
|
||||
<div class="draft-warning">DRAFT PAGE</div>
|
||||
</div><!-- /.nav -->
|
||||
|
||||
</div><!-- /.container -->
|
||||
|
||||
<div class="subnav dev_nav">
|
||||
<div class="container">
|
||||
<ul id="menu-dev-menu" class="menu">
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">References <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="reference-rippleapi.html">RippleAPI</a></li>
|
||||
<li><a href="reference-rippled.html">rippled</a></li>
|
||||
<li><a href="reference-transaction-format.html">Transaction Format</a></li>
|
||||
<li><a href="reference-ledger-format.html">Ledger Format</a></li>
|
||||
<li><a href="reference-data-api.html">Ripple Data API v2</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorials <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="tutorial-multisign.html">How to Multi-Sign</a></li>
|
||||
<li><a href="tutorial-paychan.html">Payment Channels Tutorial</a></li>
|
||||
<li><a href="concept-issuing-and-operational-addresses.html">Issuing and Operational Addresses</a></li>
|
||||
<li><a href="tutorial-reliable-transaction-submission.html">Reliable Transaction Submission</a></li>
|
||||
<li><a href="tutorial-rippleapi-beginners-guide.html">RippleAPI Beginners Guide</a></li>
|
||||
<li><a href="tutorial-rippled-setup.html">rippled Setup</a></li>
|
||||
<li><a href="tutorial-gateway-guide.html">Gateway Guide</a></li>
|
||||
<li><a href="tutorial-listing-xrp.html">Listing XRP as an Exchange</a></li>
|
||||
<li><a href="tutorial-escrow.html">Escrow Tutorials</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Features <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="concept-accounts.html">Accounts</a></li>
|
||||
<li><a href="concept-amendments.html">Amendments</a></li>
|
||||
<li><a href="concept-consensus.html">Consensus Process</a></li>
|
||||
<li><a href="concept-reaching-consensus.html">Reaching Consensus in the XRP Ledger</a></li>
|
||||
<li><a href="concept-fee-voting.html">Fee Voting</a></li>
|
||||
<li><a href="concept-fees.html">Fees (Disambiguation)</a></li>
|
||||
<li><a href="concept-freeze.html">Freeze</a></li>
|
||||
<li><a href="concept-partial-payments.html">Partial Payments</a></li>
|
||||
<li><a href="concept-paths.html">Paths</a></li>
|
||||
<li><a href="concept-reserves.html">Reserves</a></li>
|
||||
<li><a href="concept-stand-alone-mode.html">Stand-Alone Mode</a></li>
|
||||
<li><a href="concept-transaction-cost.html">Transaction Cost</a></li>
|
||||
<li><a href="concept-transfer-fees.html">Transfer Fees</a></li>
|
||||
<li><a href="concept-noripple.html">Understanding the NoRipple flag</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Gateway Bulletins <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="gb-2015-06.html">GB-2015-06: Corrections to Autobridging</a></li>
|
||||
<li><a href="gb-2015-05.html">GB-2015-05: Historical Ledger Query Migration</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">API Tools <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="ripple-api-tool.html">WebSocket API Tool</a></li>
|
||||
<li><a href="data-api-v2-tool.html">Data API v2 Tool</a></li>
|
||||
<li><a href="tool-jsonrpc.html">rippled JSON-RPC Tool</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li><a href="https://github.com/ripple/ripple-dev-portal" title="GitHub">Site Source</a></li>
|
||||
</ul><!-- /#dev-menu -->
|
||||
</div><!-- /.subnav .container -->
|
||||
</div><!-- /.subnav -->
|
||||
</header>
|
||||
|
||||
|
||||
<div class="wrap container" role="document">
|
||||
<aside class="sidebar" role="complementary">
|
||||
<div class="dev_nav_wrapper">
|
||||
<div id="cont">
|
||||
<h5>In this category:</h5>
|
||||
<ul class="dev_nav_sidebar">
|
||||
<li class="level-1"><a href="index.html">Category: Features</a></li>
|
||||
<li class="level-2"><a href="concept-accounts.html">Accounts</a></li>
|
||||
<li class="level-2"><a href="concept-amendments.html">Amendments</a></li>
|
||||
<li class="level-2"><a href="concept-consensus.html">Consensus Process</a></li>
|
||||
<li class="level-2"><a href="concept-reaching-consensus.html">Reaching Consensus in the XRP Ledger</a></li>
|
||||
<li class="level-2"><a href="concept-fee-voting.html">Fee Voting</a></li>
|
||||
<li class="level-2"><a href="concept-fees.html">Fees (Disambiguation)</a></li>
|
||||
<li class="level-2"><a href="concept-freeze.html">Freeze</a></li>
|
||||
<li class="level-2"><a href="concept-partial-payments.html">Partial Payments</a></li>
|
||||
<li class="level-2"><a href="concept-paths.html">Paths</a></li>
|
||||
<li class="level-2"><a href="concept-reserves.html">Reserves</a></li>
|
||||
<li class="level-2"><a href="concept-stand-alone-mode.html">Stand-Alone Mode</a></li>
|
||||
<li class="level-2"><a href="concept-transaction-cost.html">Transaction Cost</a></li>
|
||||
<li class="level-2"><a href="concept-transfer-fees.html">Transfer Fees</a></li>
|
||||
<li class="level-2"><a href="concept-noripple.html">Understanding the NoRipple flag</a></li>
|
||||
</ul>
|
||||
<hr />
|
||||
<h5>In this page:</h5>
|
||||
<ul class="dev_nav_sidebar" id="dactyl_toc_sidebar">
|
||||
<li class="level-1"><a href="#understanding-the-noripple-flag">Understanding the NoRipple Flag</a></li>
|
||||
<li class="level-2"><a href="#background">Background</a></li>
|
||||
<li class="level-2"><a href="#justification">Justification</a></li>
|
||||
<li class="level-2"><a href="#specifics">Specifics</a></li>
|
||||
<li class="level-2"><a href="#technical-details">Technical Details</a></li>
|
||||
<li class="level-3"><a href="#enabling-disabling-noripple">Enabling / Disabling NoRipple</a></li>
|
||||
<li class="level-3"><a href="#looking-up-noripple-status">Looking Up NoRipple Status</a></li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
<main class="main" role="main">
|
||||
<div class='content'>
|
||||
<h1 id="understanding-the-noripple-flag">Understanding the NoRipple Flag</h1>
|
||||
<p>In the XRP Ledger, the "NoRipple" flag is a setting on a trust line. When an address enables the NoRipple flag on two trust lines, payments from third parties cannot "ripple" through that address on those trust lines. This protects liquidity providers from having balances shift unexpectedly between different issuers of the same currency.</p>
|
||||
<h2 id="background">Background</h2>
|
||||
<p>"Rippling" occurs when more than one trust line is adjusted to make a payment. For example, if Alice owes Charlie money, and Alice also owes Bob money, then you could represent that in the XRP Ledger with trust lines like so:</p>
|
||||
<p><img alt="Charlie --($10)-- Alice -- ($20) -- Bob" src="img/noripple-01.png"/></p>
|
||||
<p>If Bob wants to pay $3 to Charlie, then he could say, "Alice, take $3 of the money you owe me, and pay it to Charlie." Alice transfers some of the debt from Bob to Charlie. In the end, the trust lines work out like so:</p>
|
||||
<p><img alt="Charlie --($13)-- Alice --($17)-- Bob" src="img/noripple-02.png"/></p>
|
||||
<p>We call this process, where two addresses pay each other by adjusting the balances of trust lines in between them, "rippling". This is a useful and important feature of the XRP Ledger. Rippling occurs when addresses are linked by trust lines that use the same <a href="reference-rippled.html#currency-codes">currency code</a>. The issuer does not need to be the same: in fact, larger chains always involve changing issuers.</p>
|
||||
<h2 id="justification">Justification</h2>
|
||||
<p>Sometimes you do not want your balances to ripple. For example, imagine Emily has money issued by two different financial institutions, like so</p>
|
||||
<p><img alt="Charlie --($10)-- Institution A --($1)-- Emily --($100)-- Institution B --($2)-- Daniel" src="img/noripple-03.png"/></p>
|
||||
<p>Now Charlie can pay Daniel by rippling through Emily's address. For example, if Charlie pays Daniel $10:</p>
|
||||
<p><img alt="Charlie --($0)-- Institution A --($11)-- Emily --($90)-- Institution B --($12)-- Daniel" src="img/noripple-04.png"/></p>
|
||||
<p>This may surprise Emily, who does not know Charlie or Daniel. Even worse, if Institution A charges her higher fees to withdraw her money than Institution B, this could cost Emily money. The NoRipple flag exists to avoid this scenario. If Emily sets it on both trust lines, then payments cannot ripple through her address using those two trust lines.</p>
|
||||
<p>For example:</p>
|
||||
<p><img alt="Charlie --($10)-- Institution A --($1, NoRipple)-- Emily --($100,NoRipple)-- Institution B --($2)-- Daniel" src="img/noripple-05.png"/></p>
|
||||
<p>Now the above scenario, where Charlie pays Daniel while rippling through Emily's address, is no longer possible.</p>
|
||||
<h2 id="specifics">Specifics</h2>
|
||||
<p>The NoRipple flag makes certain paths invalid, so that they cannot be used to make payments. A path is considered invalid if and only if it enters <strong>and</strong> exits an address node through trust lines where NoRipple has been enabled for that address.</p>
|
||||
<p><img alt="Diagram demonstrating that NoRipple has to be set on both trust lines by the same address to do anything" src="img/noripple-06.png"/></p>
|
||||
<h2 id="technical-details">Technical Details</h2>
|
||||
<h3 id="enabling-disabling-noripple">Enabling / Disabling NoRipple</h3>
|
||||
<p>The NoRipple flag can only be enabled on a trust line if the address has a positive or zero balance on that trust line. This is so that the feature cannot be abused to default on the obligation the trust line balance represents. (Of course, you can still default by abandoning the address.)</p>
|
||||
<p>In the <a href="reference-rippled.html"><code>rippled</code> APIs</a>, you can enable the NoRipple flag by sending a <a href="reference-transaction-format.html#trustset">TrustSet Transaction</a> with the <code>tfSetNoRipple</code> flag. You can disable NoRipple (enable rippling) with the <code>tfClearNoRipple</code> flag.</p>
|
||||
<p>In <a href="reference-rippleapi.html">RippleAPI</a>, you can enable the NoRipple flag by sending a <a href="reference-rippleapi.html#preparetrustline">Trustline transaction</a> transaction with the <code>ripplingDisabled</code> field of the trust line set to <code>true</code>.</p>
|
||||
<h3 id="looking-up-noripple-status">Looking Up NoRipple Status</h3>
|
||||
<p>In the case of two accounts that mutually trust each other, the NoRipple flag is tracked separately for each account.</p>
|
||||
<p>In the <a href="reference-rippled.html"><code>rippled</code> APIs</a>, you can use the <a href="https://ripple.com/build/rippled-apis/#account-lines">account_lines method</a> to look up the trust lines associated with an address. For each trust line, the <code>no_ripple</code> field shows whether the current address has enabled the NoRipple flag on that trust line, and the <code>no_ripple_peer</code> field shows whether the counterparty has enabled the NoRipple flag.</p>
|
||||
<p>In <a href="reference-rippleapi.html">RippleAPI</a>, you can use the <a href="reference-rippleapi.html#gettrustlines">getTrustlines</a> method to look up the trust lines associated with an address. For each trust line, the <code>ripplingDisabled</code> field shows whether the current address has enabled the NoRipple flag on that trust line, and the <code>counterparty.ripplingDisabled</code> field shows whether the counterparty has enabled the NoRipple flag.</p>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<footer class="content-info" role="contentinfo">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-sm-12 absolute_bottom_footer">
|
||||
<div class="col-sm-8">
|
||||
<span>© 2013 - 2017 Ripple Labs, Inc. All Rights Reserved.</span>
|
||||
<span><a href="/terms-of-use/">Terms</a></span>
|
||||
<span><a href="/privacy-policy/">Privacy</a></span>
|
||||
</div>
|
||||
</div><!-- /.absolute_bottom_footer -->
|
||||
|
||||
</div><!-- /.row -->
|
||||
</div><!-- /.container -->
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,293 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<meta name="viewport" content="width=device-width">
|
||||
|
||||
<title>Partial Payments - Ripple Developer Portal</title>
|
||||
|
||||
<!-- favicon -->
|
||||
<link rel="icon" href="favicon.ico" type="image/x-icon">
|
||||
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon">
|
||||
|
||||
<!-- jQuery -->
|
||||
<script src="assets/vendor/jquery-1.11.1.min.js"></script>
|
||||
|
||||
<!-- Custom Stylesheets. ripple.css includes bootstrap, font stuff -->
|
||||
<link href="assets/css/ripple.css" rel="stylesheet" />
|
||||
<link href="assets/css/devportal.css" rel="stylesheet" />
|
||||
|
||||
<!-- Bootstrap JS -->
|
||||
<script src="assets/vendor/bootstrap.min.js"></script>
|
||||
|
||||
|
||||
<!-- syntax highlighting -->
|
||||
<link rel="stylesheet" href="assets/vendor/docco.min.css" />
|
||||
<script src="assets/vendor/highlight.min.js"></script>
|
||||
|
||||
<!-- syntax selection js -->
|
||||
<script src="assets/js/multicodetab.js"></script>
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
$(".multicode").minitabs();
|
||||
hljs.initHighlighting();
|
||||
make_code_expandable();
|
||||
});
|
||||
</script>
|
||||
|
||||
<script src="assets/js/expandcode.js"></script>
|
||||
<script src="assets/js/fixsidebarscroll.js"></script>
|
||||
|
||||
<!-- fontawesome icons -->
|
||||
<link rel="stylesheet" href="assets/vendor/fontawesome/css/font-awesome.min.css" />
|
||||
|
||||
</head>
|
||||
|
||||
<body class="page page-template page-template-template-dev-portal page-template-template-dev-portal-php sidebar-primary wpb-js-composer js-comp-ver-3.6.2 vc_responsive">
|
||||
<header role="banner" class="banner navbar navbar-default navbar-fixed-top initial_header">
|
||||
<div class="container">
|
||||
<div class="navbar-header">
|
||||
<a href="index.html" class="navbar-brand"><img src="assets/img/ripple-logo-color.png" class="logo"></a>
|
||||
</div><!-- /.navbar-header -->
|
||||
<div class="nav">
|
||||
<div class="draft-warning">DRAFT PAGE</div>
|
||||
</div><!-- /.nav -->
|
||||
|
||||
</div><!-- /.container -->
|
||||
|
||||
<div class="subnav dev_nav">
|
||||
<div class="container">
|
||||
<ul id="menu-dev-menu" class="menu">
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">References <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="reference-rippleapi.html">RippleAPI</a></li>
|
||||
<li><a href="reference-rippled.html">rippled</a></li>
|
||||
<li><a href="reference-transaction-format.html">Transaction Format</a></li>
|
||||
<li><a href="reference-ledger-format.html">Ledger Format</a></li>
|
||||
<li><a href="reference-data-api.html">Ripple Data API v2</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorials <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="tutorial-multisign.html">How to Multi-Sign</a></li>
|
||||
<li><a href="tutorial-paychan.html">Payment Channels Tutorial</a></li>
|
||||
<li><a href="concept-issuing-and-operational-addresses.html">Issuing and Operational Addresses</a></li>
|
||||
<li><a href="tutorial-reliable-transaction-submission.html">Reliable Transaction Submission</a></li>
|
||||
<li><a href="tutorial-rippleapi-beginners-guide.html">RippleAPI Beginners Guide</a></li>
|
||||
<li><a href="tutorial-rippled-setup.html">rippled Setup</a></li>
|
||||
<li><a href="tutorial-gateway-guide.html">Gateway Guide</a></li>
|
||||
<li><a href="tutorial-listing-xrp.html">Listing XRP as an Exchange</a></li>
|
||||
<li><a href="tutorial-escrow.html">Escrow Tutorials</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Features <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="concept-accounts.html">Accounts</a></li>
|
||||
<li><a href="concept-amendments.html">Amendments</a></li>
|
||||
<li><a href="concept-consensus.html">Consensus Process</a></li>
|
||||
<li><a href="concept-reaching-consensus.html">Reaching Consensus in the XRP Ledger</a></li>
|
||||
<li><a href="concept-fee-voting.html">Fee Voting</a></li>
|
||||
<li><a href="concept-fees.html">Fees (Disambiguation)</a></li>
|
||||
<li><a href="concept-freeze.html">Freeze</a></li>
|
||||
<li><a href="concept-partial-payments.html">Partial Payments</a></li>
|
||||
<li><a href="concept-paths.html">Paths</a></li>
|
||||
<li><a href="concept-reserves.html">Reserves</a></li>
|
||||
<li><a href="concept-stand-alone-mode.html">Stand-Alone Mode</a></li>
|
||||
<li><a href="concept-transaction-cost.html">Transaction Cost</a></li>
|
||||
<li><a href="concept-transfer-fees.html">Transfer Fees</a></li>
|
||||
<li><a href="concept-noripple.html">Understanding the NoRipple flag</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Gateway Bulletins <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="gb-2015-06.html">GB-2015-06: Corrections to Autobridging</a></li>
|
||||
<li><a href="gb-2015-05.html">GB-2015-05: Historical Ledger Query Migration</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">API Tools <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="ripple-api-tool.html">WebSocket API Tool</a></li>
|
||||
<li><a href="data-api-v2-tool.html">Data API v2 Tool</a></li>
|
||||
<li><a href="tool-jsonrpc.html">rippled JSON-RPC Tool</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li><a href="https://github.com/ripple/ripple-dev-portal" title="GitHub">Site Source</a></li>
|
||||
</ul><!-- /#dev-menu -->
|
||||
</div><!-- /.subnav .container -->
|
||||
</div><!-- /.subnav -->
|
||||
</header>
|
||||
|
||||
|
||||
<div class="wrap container" role="document">
|
||||
<aside class="sidebar" role="complementary">
|
||||
<div class="dev_nav_wrapper">
|
||||
<div id="cont">
|
||||
<h5>In this category:</h5>
|
||||
<ul class="dev_nav_sidebar">
|
||||
<li class="level-1"><a href="index.html">Category: Features</a></li>
|
||||
<li class="level-2"><a href="concept-accounts.html">Accounts</a></li>
|
||||
<li class="level-2"><a href="concept-amendments.html">Amendments</a></li>
|
||||
<li class="level-2"><a href="concept-consensus.html">Consensus Process</a></li>
|
||||
<li class="level-2"><a href="concept-reaching-consensus.html">Reaching Consensus in the XRP Ledger</a></li>
|
||||
<li class="level-2"><a href="concept-fee-voting.html">Fee Voting</a></li>
|
||||
<li class="level-2"><a href="concept-fees.html">Fees (Disambiguation)</a></li>
|
||||
<li class="level-2"><a href="concept-freeze.html">Freeze</a></li>
|
||||
<li class="level-2"><a href="concept-partial-payments.html">Partial Payments</a></li>
|
||||
<li class="level-2"><a href="concept-paths.html">Paths</a></li>
|
||||
<li class="level-2"><a href="concept-reserves.html">Reserves</a></li>
|
||||
<li class="level-2"><a href="concept-stand-alone-mode.html">Stand-Alone Mode</a></li>
|
||||
<li class="level-2"><a href="concept-transaction-cost.html">Transaction Cost</a></li>
|
||||
<li class="level-2"><a href="concept-transfer-fees.html">Transfer Fees</a></li>
|
||||
<li class="level-2"><a href="concept-noripple.html">Understanding the NoRipple flag</a></li>
|
||||
</ul>
|
||||
<hr />
|
||||
<h5>In this page:</h5>
|
||||
<ul class="dev_nav_sidebar" id="dactyl_toc_sidebar">
|
||||
<li class="level-1"><a href="#partial-payments">Partial Payments</a></li>
|
||||
<li class="level-2"><a href="#semantics">Semantics</a></li>
|
||||
<li class="level-3"><a href="#without-partial-payments">Without Partial Payments</a></li>
|
||||
<li class="level-3"><a href="#with-partial-payments">With Partial Payments</a></li>
|
||||
<li class="level-3"><a href="#partial-payment-limitations">Partial Payment Limitations</a></li>
|
||||
<li class="level-3"><a href="#the-delivered-amount-field">The delivered_amount Field</a></li>
|
||||
<li class="level-2"><a href="#partial-payments-exploit">Partial Payments Exploit</a></li>
|
||||
<li class="level-3"><a href="#exploit-scenario-steps">Exploit Scenario Steps</a></li>
|
||||
<li class="level-3"><a href="#further-mitigations">Further Mitigations</a></li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
<main class="main" role="main">
|
||||
<div class='content'>
|
||||
<h1 id="partial-payments">Partial Payments</h1>
|
||||
<p>In the default case, the <code>Amount</code> field of a <a href="reference-transaction-format.html#payment">Payment transaction</a> in the XRP Ledger specifies the exact amount to deliver, after charging for exchange rates and <a href="concept-transfer-fees.html">transfer fees</a>. The "Partial Payment" flag (<a href="reference-transaction-format.html#payment-flags"><strong>tfPartialPayment</strong></a>) allows a payment to succeed by reducing the amount received instead of increasing the amount sent. Partial payments are useful for <a href="tutorial-gateway-guide.html#bouncing-payments">returning payments</a> without incurring additional costs to oneself.</p>
|
||||
<p>The amount of XRP used for the <a href="concept-transaction-cost.html">transaction cost</a> is always deducted from the sender’s account, regardless of the type of transaction.</p>
|
||||
<p>Partial payments can be used to exploit naive integrations with the XRP Ledger to steal money from exchanges and gateways. The <a href="#partial-payments-exploit">Partial Payments Exploit</a> section of this document describes how this exploit works and how you can avoid it.</p>
|
||||
<h2 id="semantics">Semantics</h2>
|
||||
<h3 id="without-partial-payments">Without Partial Payments</h3>
|
||||
<p>When sending a Payment that does not use the Partial Payment flag, the <code>Amount</code> field of the transaction specifies the exact amount to deliver, and the <code>SendMax</code> field specifies the maximum amount and currency to send. If a payment cannot deliver the full <code>Amount</code> without exceeding the <code>SendMax</code> parameter, or the full amount cannot be delivered for any other reason, the transaction fails. If the <code>SendMax</code> field is omitted from the transaction instructions, it is considered to be equal to the <code>Amount</code>. In this case, the payment can only succeed if the total amount of fees is 0.</p>
|
||||
<p>In other words:</p>
|
||||
<pre><code>Amount + (fees) = (sent amount) ≤ SendMax
|
||||
</code></pre>
|
||||
<p>In this formula, "fees" refers to <a href="concept-transfer-fees.html">transfer fees</a> and currency exchange rates. The "sent amount" and the delivered amount (<code>Amount</code>) may be denominated in different currencies and converted by consuming Offers in the XRP Ledger's decentralized exchange.</p>
|
||||
<p class="devportal-callout note"><strong>Note:</strong> The <code>Fee</code> field of the transaction refers to the XRP <a href="concept-transaction-cost.html">transaction cost</a>, 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.</p>
|
||||
<h3 id="with-partial-payments">With Partial Payments</h3>
|
||||
<p>When sending a Payment that has the Partial Payment flag enabled, the <code>Amount</code> field of the transaction specifies a maximum amount to deliver. Partial payments can succeed at sending <em>some</em> of the intended value despite limitations including fees, lack of liquidity, insufficient space in the receiving account's trust lines, or other reasons.</p>
|
||||
<p>The optional <code>DeliverMin</code> field specifies a minimum amount to deliver. The <code>SendMax</code> 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 <code>DeliverMin</code> field without exceeding the <code>SendMax</code> amount. If the <code>DeliverMin</code> field is not specified, a partial payment can succeed by delivering any positive amount.</p>
|
||||
<p>In other words:</p>
|
||||
<pre><code>Amount ≥ (Delivered Amount) = SendMax - (Fees) ≥ DeliverMin > 0
|
||||
</code></pre>
|
||||
<h3 id="partial-payment-limitations">Partial Payment Limitations</h3>
|
||||
<p>Partial Payments have the following limitations:</p>
|
||||
<ul>
|
||||
<li>A partial payment cannot provide the XRP to fund an address; this case returns the <a href="reference-transaction-format.html#transaction-results">result code</a> <code>telNO_DST_PARTIAL</code>.</li>
|
||||
<li>Direct XRP-to-XRP payments cannot be partial payments; this case returns the <a href="reference-transaction-format.html#transaction-results">result code</a> <code>temBAD_SEND_XRP_PARTIAL</code>.<ul>
|
||||
<li>However, issuance-to-XRP payments or XRP-to-issuance payments <em>can</em> be partial payments.</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<h3 id="the-delivered-amount-field">The <code>delivered_amount</code> Field</h3>
|
||||
<p>To help understand how much a partial payment actually delivered, the metadata of a successful Payment transaction includes a <code>delivered_amount</code> field. This field describes the amount actually delivered, in the <a href="reference-rippled.html#specifying-currency-amounts">same format</a> as the <code>Amount</code> field.</p>
|
||||
<p>For non-partial payments, the <code>delivered_amount</code> field of the transaction metadata is equal to the <code>Amount</code> field of the transaction. When a payment delivers an issued currency, the <code>delivered_amount</code> may be slightly different than the <code>Amount</code> field due to rounding.</p>
|
||||
<p>The delivered amount is <strong>not available</strong> for transactions that meet <strong>both</strong> of the following criteria:</p>
|
||||
<ul>
|
||||
<li>Is a partial payment</li>
|
||||
<li>Is included in a validated ledger before 2014-01-20</li>
|
||||
</ul>
|
||||
<p>If both conditions are true, then <code>delivered_amount</code> contains the string value <code>unavailable</code> 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 an issued currency and the <code>issuer</code> of the <code>Amount</code> is the same account as the <code>Destination</code> address, the delivered amount may be divided among multiple <code>AffectedNodes</code> members representing trust lines to different counterparties.</p>
|
||||
<p>You can find the <code>delivered_amount</code> field in the following places:</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>API</th>
|
||||
<th>Method</th>
|
||||
<th>Field</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><a href="reference-rippled.html">JSON-RPC / WebSocket</a></td>
|
||||
<td><a href="reference-rippled.html#account-tx"><code>account_tx</code> command</a></td>
|
||||
<td><code>result.transactions</code> array members' <code>meta.delivered_amount</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="reference-rippled.html">JSON-RPC / WebSocket</a></td>
|
||||
<td><a href="reference-rippled.html#tx"><code>tx</code> command</a></td>
|
||||
<td><code>result.meta.delivered_amount</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="reference-rippled.html">JSON-RPC / WebSocket</a></td>
|
||||
<td><a href="reference-rippled.html#transaction-entry"><code>transaction_entry</code> command</a></td>
|
||||
<td><code>result.metadata.delivered_amount</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="reference-rippleapi.html">RippleAPI</a></td>
|
||||
<td><a href="reference-rippleapi.html#gettransaction"><code>getTransaction</code> method</a></td>
|
||||
<td><code>outcome.deliveredAmount</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="reference-rippleapi.html">RippleAPI</a></td>
|
||||
<td><a href="reference-rippleapi.html#gettransactions"><code>getTransactions</code> method</a></td>
|
||||
<td>array members' <code>outcome.deliveredAmount</code></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h2 id="partial-payments-exploit">Partial Payments Exploit</h2>
|
||||
<p>If a financial institution's integration with the XRP Ledger assumes that the <code>Amount</code> 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.</p>
|
||||
<p><strong>The correct way to process incoming Payment transactions is to use <a href="#the-delivered-amount-field">the <code>delivered_amount</code> metadata field</a>,</strong> not the <code>Amount</code> field. This way, an institution is never mistaken about how much it <em>actually</em> received.</p>
|
||||
<h3 id="exploit-scenario-steps">Exploit Scenario Steps</h3>
|
||||
<p>To exploit a vulnerable financial institution, a malicious actor does something like this:</p>
|
||||
<ol>
|
||||
<li>The malicious actor sends a Payment transaction to the institution. This transaction has a large <code>Amount</code> field and has the <strong>tfPartialPayment</strong> flag enabled.</li>
|
||||
<li>The partial payment succeeds (result code <code>tesSUCCESS</code>) but actually delivers a very small amount of the currency specified.</li>
|
||||
<li>The vulnerable institution reads the transaction's <code>Amount</code> field without looking at the <code>Flags</code> field or <code>delivered_amount</code> metadata field.</li>
|
||||
<li>The vulnerable institution credits the malicious actor in an external system, such as the institution's own ledger, for the full <code>Amount</code>, despite only receiving a much smaller <code>delivered_amount</code> in the XRP Ledger.</li>
|
||||
<li>The malicious actor withdraws as much of the balance as possible to another system before the vulnerable institution notices the discrepancy.<ul>
|
||||
<li>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.</li>
|
||||
<li>In the case of an exchange, the malicious actor can also withdraw an XRP balance directly back into the XRP Ledger.</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ol>
|
||||
<p>In the case of a merchant, the order of operations is slightly different, but the concept is the same:</p>
|
||||
<ol>
|
||||
<li>The malicious actor requests to buy a large amount of goods or services.</li>
|
||||
<li>The vulnerable merchant invoices the malicious actor for the price of those goods and services.</li>
|
||||
<li>The malicious actor sends a Payment transaction to the merchant. This transaction has a large <code>Amount</code> field and has the <strong>tfPartialPayment</strong> flag enabled.</li>
|
||||
<li>The partial payment succeeds (result code <code>tesSUCCESS</code>) but delivers only a very small amount of the currency specified.</li>
|
||||
<li>The vulnerable merchant reads the transaction's <code>Amount</code> field without looking at the <code>Flags</code> field or <code>delivered_amount</code> metadata field.</li>
|
||||
<li>The vulnerable merchant treats the invoice as paid and provides the goods or services to the malicious actor, despite only receiving a much smaller <code>delivered_amount</code> in the XRP Ledger.</li>
|
||||
<li>The malicious actor uses, resells, or absconds with the goods and services before the merchant notices the discrepancy.</li>
|
||||
</ol>
|
||||
<h3 id="further-mitigations">Further Mitigations</h3>
|
||||
<p>Using <a href="#the-delivered-amount-field">the <code>delivered_amount</code> field</a> when processing incoming transactions is sufficient to avoid this exploit. Still, additional proactive business practices can also avoid or mitigate the likelihood of this and similar exploits. For example:</p>
|
||||
<ul>
|
||||
<li>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.</li>
|
||||
<li>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.</li>
|
||||
</ul>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<footer class="content-info" role="contentinfo">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-sm-12 absolute_bottom_footer">
|
||||
<div class="col-sm-8">
|
||||
<span>© 2013 - 2017 Ripple Labs, Inc. All Rights Reserved.</span>
|
||||
<span><a href="/terms-of-use/">Terms</a></span>
|
||||
<span><a href="/privacy-policy/">Privacy</a></span>
|
||||
</div>
|
||||
</div><!-- /.absolute_bottom_footer -->
|
||||
|
||||
</div><!-- /.row -->
|
||||
</div><!-- /.container -->
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,304 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<meta name="viewport" content="width=device-width">
|
||||
|
||||
<title>Paths - Ripple Developer Portal</title>
|
||||
|
||||
<!-- favicon -->
|
||||
<link rel="icon" href="favicon.ico" type="image/x-icon">
|
||||
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon">
|
||||
|
||||
<!-- jQuery -->
|
||||
<script src="assets/vendor/jquery-1.11.1.min.js"></script>
|
||||
|
||||
<!-- Custom Stylesheets. ripple.css includes bootstrap, font stuff -->
|
||||
<link href="assets/css/ripple.css" rel="stylesheet" />
|
||||
<link href="assets/css/devportal.css" rel="stylesheet" />
|
||||
|
||||
<!-- Bootstrap JS -->
|
||||
<script src="assets/vendor/bootstrap.min.js"></script>
|
||||
|
||||
|
||||
<!-- syntax highlighting -->
|
||||
<link rel="stylesheet" href="assets/vendor/docco.min.css" />
|
||||
<script src="assets/vendor/highlight.min.js"></script>
|
||||
|
||||
<!-- syntax selection js -->
|
||||
<script src="assets/js/multicodetab.js"></script>
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
$(".multicode").minitabs();
|
||||
hljs.initHighlighting();
|
||||
make_code_expandable();
|
||||
});
|
||||
</script>
|
||||
|
||||
<script src="assets/js/expandcode.js"></script>
|
||||
<script src="assets/js/fixsidebarscroll.js"></script>
|
||||
|
||||
<!-- fontawesome icons -->
|
||||
<link rel="stylesheet" href="assets/vendor/fontawesome/css/font-awesome.min.css" />
|
||||
|
||||
</head>
|
||||
|
||||
<body class="page page-template page-template-template-dev-portal page-template-template-dev-portal-php sidebar-primary wpb-js-composer js-comp-ver-3.6.2 vc_responsive">
|
||||
<header role="banner" class="banner navbar navbar-default navbar-fixed-top initial_header">
|
||||
<div class="container">
|
||||
<div class="navbar-header">
|
||||
<a href="index.html" class="navbar-brand"><img src="assets/img/ripple-logo-color.png" class="logo"></a>
|
||||
</div><!-- /.navbar-header -->
|
||||
<div class="nav">
|
||||
<div class="draft-warning">DRAFT PAGE</div>
|
||||
</div><!-- /.nav -->
|
||||
|
||||
</div><!-- /.container -->
|
||||
|
||||
<div class="subnav dev_nav">
|
||||
<div class="container">
|
||||
<ul id="menu-dev-menu" class="menu">
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">References <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="reference-rippleapi.html">RippleAPI</a></li>
|
||||
<li><a href="reference-rippled.html">rippled</a></li>
|
||||
<li><a href="reference-transaction-format.html">Transaction Format</a></li>
|
||||
<li><a href="reference-ledger-format.html">Ledger Format</a></li>
|
||||
<li><a href="reference-data-api.html">Ripple Data API v2</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorials <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="tutorial-multisign.html">How to Multi-Sign</a></li>
|
||||
<li><a href="tutorial-paychan.html">Payment Channels Tutorial</a></li>
|
||||
<li><a href="concept-issuing-and-operational-addresses.html">Issuing and Operational Addresses</a></li>
|
||||
<li><a href="tutorial-reliable-transaction-submission.html">Reliable Transaction Submission</a></li>
|
||||
<li><a href="tutorial-rippleapi-beginners-guide.html">RippleAPI Beginners Guide</a></li>
|
||||
<li><a href="tutorial-rippled-setup.html">rippled Setup</a></li>
|
||||
<li><a href="tutorial-gateway-guide.html">Gateway Guide</a></li>
|
||||
<li><a href="tutorial-listing-xrp.html">Listing XRP as an Exchange</a></li>
|
||||
<li><a href="tutorial-escrow.html">Escrow Tutorials</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Features <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="concept-accounts.html">Accounts</a></li>
|
||||
<li><a href="concept-amendments.html">Amendments</a></li>
|
||||
<li><a href="concept-consensus.html">Consensus Process</a></li>
|
||||
<li><a href="concept-reaching-consensus.html">Reaching Consensus in the XRP Ledger</a></li>
|
||||
<li><a href="concept-fee-voting.html">Fee Voting</a></li>
|
||||
<li><a href="concept-fees.html">Fees (Disambiguation)</a></li>
|
||||
<li><a href="concept-freeze.html">Freeze</a></li>
|
||||
<li><a href="concept-partial-payments.html">Partial Payments</a></li>
|
||||
<li><a href="concept-paths.html">Paths</a></li>
|
||||
<li><a href="concept-reserves.html">Reserves</a></li>
|
||||
<li><a href="concept-stand-alone-mode.html">Stand-Alone Mode</a></li>
|
||||
<li><a href="concept-transaction-cost.html">Transaction Cost</a></li>
|
||||
<li><a href="concept-transfer-fees.html">Transfer Fees</a></li>
|
||||
<li><a href="concept-noripple.html">Understanding the NoRipple flag</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Gateway Bulletins <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="gb-2015-06.html">GB-2015-06: Corrections to Autobridging</a></li>
|
||||
<li><a href="gb-2015-05.html">GB-2015-05: Historical Ledger Query Migration</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">API Tools <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="ripple-api-tool.html">WebSocket API Tool</a></li>
|
||||
<li><a href="data-api-v2-tool.html">Data API v2 Tool</a></li>
|
||||
<li><a href="tool-jsonrpc.html">rippled JSON-RPC Tool</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li><a href="https://github.com/ripple/ripple-dev-portal" title="GitHub">Site Source</a></li>
|
||||
</ul><!-- /#dev-menu -->
|
||||
</div><!-- /.subnav .container -->
|
||||
</div><!-- /.subnav -->
|
||||
</header>
|
||||
|
||||
|
||||
<div class="wrap container" role="document">
|
||||
<aside class="sidebar" role="complementary">
|
||||
<div class="dev_nav_wrapper">
|
||||
<div id="cont">
|
||||
<h5>In this category:</h5>
|
||||
<ul class="dev_nav_sidebar">
|
||||
<li class="level-1"><a href="index.html">Category: Features</a></li>
|
||||
<li class="level-2"><a href="concept-accounts.html">Accounts</a></li>
|
||||
<li class="level-2"><a href="concept-amendments.html">Amendments</a></li>
|
||||
<li class="level-2"><a href="concept-consensus.html">Consensus Process</a></li>
|
||||
<li class="level-2"><a href="concept-reaching-consensus.html">Reaching Consensus in the XRP Ledger</a></li>
|
||||
<li class="level-2"><a href="concept-fee-voting.html">Fee Voting</a></li>
|
||||
<li class="level-2"><a href="concept-fees.html">Fees (Disambiguation)</a></li>
|
||||
<li class="level-2"><a href="concept-freeze.html">Freeze</a></li>
|
||||
<li class="level-2"><a href="concept-partial-payments.html">Partial Payments</a></li>
|
||||
<li class="level-2"><a href="concept-paths.html">Paths</a></li>
|
||||
<li class="level-2"><a href="concept-reserves.html">Reserves</a></li>
|
||||
<li class="level-2"><a href="concept-stand-alone-mode.html">Stand-Alone Mode</a></li>
|
||||
<li class="level-2"><a href="concept-transaction-cost.html">Transaction Cost</a></li>
|
||||
<li class="level-2"><a href="concept-transfer-fees.html">Transfer Fees</a></li>
|
||||
<li class="level-2"><a href="concept-noripple.html">Understanding the NoRipple flag</a></li>
|
||||
</ul>
|
||||
<hr />
|
||||
<h5>In this page:</h5>
|
||||
<ul class="dev_nav_sidebar" id="dactyl_toc_sidebar">
|
||||
<li class="level-1"><a href="#paths">Paths</a></li>
|
||||
<li class="level-2"><a href="#path-steps">Path Steps</a></li>
|
||||
<li class="level-1"><a href="#technical-details">Technical Details</a></li>
|
||||
<li class="level-2"><a href="#pathfinding">Pathfinding</a></li>
|
||||
<li class="level-2"><a href="#implied-steps">Implied Steps</a></li>
|
||||
<li class="level-2"><a href="#default-paths">Default Paths</a></li>
|
||||
<li class="level-2"><a href="#path-specifications">Path Specifications</a></li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
<main class="main" role="main">
|
||||
<div class='content'>
|
||||
<h1 id="paths">Paths</h1>
|
||||
<p>In the XRP Ledger, paths define a way for payments to flow through intermediary steps on their way from sender to receiver. Paths enable cross-currency payments by connecting sender and receiver through order books. Paths also enable complex settlement of offsetting debts.</p>
|
||||
<p>A single Payment transaction in the XRP Ledger can use multiple paths, combining liquidity from different sources to deliver the desired amount. Thus, a transaction includes a <em>path set</em>, which is a collection of possible paths to take. The paths in a path set must start and end with the same currency.</p>
|
||||
<p>Since XRP can be sent directly to any address, an XRP-to-XRP transaction does not use any paths.</p>
|
||||
<h2 id="path-steps">Path Steps</h2>
|
||||
<p>A path is made of steps that connect the sender to the receiver of the payment. Every step is either:</p>
|
||||
<ul>
|
||||
<li>Rippling through another address with the same currency</li>
|
||||
<li>Exchanging currency at an order book</li>
|
||||
</ul>
|
||||
<p>Rippling through another address is the process of moving debt around. In the typical case, this involves reducing an issuer's obligation to one party and increasing the obligation to another party. Rippling can occur between any addresses that are connected by trust lines. See <a href="concept-noripple.html">Understanding the NoRipple Flag</a> for more examples of rippling.</p>
|
||||
<p>In the case of a currency exchange step, the path step specifies which currency to change to, but does not record the state of the Offers in the order book. The canonical order of transactions is not final until a ledger is validated, so you cannot know for certain which Offers a transaction will take, until after the transaction has been validated. (You can make an educated guess, since each transaction takes the best available Offers at the time it executes in the final ledger.) <!-- STYLE_OVERRIDE: will --></p>
|
||||
<p>In both types of steps, each intermediate address gains and loses approximately equal value: either a balance ripples from a trust line to another trust line in the same currency, or they exchange currencies according to a previously-placed order. In some cases, the amounts gained and lost may not be exactly equivalent, due to <a href="concept-transfer-fees.html">transfer fees</a>, trust line quality, or rounding.</p>
|
||||
<p><a href="img/paths-examples.png"><img alt="Diagram of three example paths" src="img/paths-examples.png"/></a></p>
|
||||
<h1 id="technical-details">Technical Details</h1>
|
||||
<h2 id="pathfinding">Pathfinding</h2>
|
||||
<p>The <code>rippled</code> API has two methods that can be used for pathfinding. The <a href="reference-rippled.html#ripple-path-find"><code>ripple_path_find</code> command</a> does a one-time lookup of possible path sets. The <a href="reference-rippled.html#path-find"><code>path_find</code> command</a> (WebSocket only) expands on the search with follow-up responses whenever a ledger closes or the server finds a better path.</p>
|
||||
<p>You can have <code>rippled</code> automatically fill in paths when you sign it, by including the <code>build_path</code> field in a request to the <a href="reference-rippled.html#sign"><code>sign</code> command</a> or <a href="reference-rippled.html#sign-and-submit-mode"><code>submit</code> command (sign-and-submit mode)</a>. However, we recommend pathfinding separately and confirming the results before signing, to avoid surprises.</p>
|
||||
<p class="devportal-callout caution"><strong>Caution:</strong> Although <code>rippled</code> is designed to search for the cheapest paths possible, it may not always find them. Untrustworthy <code>rippled</code> instances could also be modified to change this behavior for profit. The actual cost to execute a payment along a path can change between submission and transaction execution.</p>
|
||||
<p>Finding paths is a very challenging problem that changes slightly every few seconds as new ledgers are validated, so <code>rippled</code> is not designed to find the absolute best path. Still, you can find several possible paths and estimate the cost of delivering a particular amount.</p>
|
||||
<h2 id="implied-steps">Implied Steps</h2>
|
||||
<p>By convention, several steps of a path are implied by the <a href="reference-transaction-format.html#payment">fields of the Payment transaction</a>: specifically, the <code>Account</code> (sender), <code>Destination</code> (receiver), <code>Amount</code> (currency and amount to be delivered) and <code>SendMax</code> (currency and amount to be sent, if specified). The implied steps are as follows:</p>
|
||||
<ul>
|
||||
<li>The first step of a path is always implied to be the sender of the transaction, as defined by the transaction's <code>Account</code> field.</li>
|
||||
<li>If the transaction includes a <code>SendMax</code> field with an <code>issuer</code> that is not the sender of the transaction, that issuer is implied to be the second step of the path.<ul>
|
||||
<li>If <code>issuer</code> of the <code>SendMax</code> <em>is</em> the sending address, then the path starts at the sending address, and may use any of that address's trust lines in the given currency. See <a href="reference-transaction-format.html#special-issuer-values-for-sendmax-and-amount">special values for SendMax and Amount</a> for details.</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>If the <code>Amount</code> field of the transaction includes an <code>issuer</code> that is not the same as the <code>Destination</code> of the transaction, that issuer is implied to be the second-to-last step of the path.</li>
|
||||
<li>Finally, last step of a path is always implied to be the receiver of a transaction, as defined by the transaction's <code>Destination</code> field.</li>
|
||||
</ul>
|
||||
<h2 id="default-paths">Default Paths</h2>
|
||||
<p>In addition to explicitly specified paths, a transaction can execute along the <em>default path</em>. The default path is the simplest possible way to connect the <a href="#implied-steps">implied steps</a> of the transaction.</p>
|
||||
<p>The default path could be any of the following:</p>
|
||||
<ul>
|
||||
<li>If the transaction is uses only one currency (regardless of issuer), then the default path assumes the payment should ripple through the addresses involved. This path only works if those addresses are connected by trust lines.<ul>
|
||||
<li>If <code>SendMax</code> is omitted, or the <code>issuer</code> of the <code>SendMax</code> is the sender, the default path needs a trust line from the sending <code>Account</code> to the <code>issuer</code> of the destination <code>Amount</code> to work.</li>
|
||||
<li>If the <code>SendMax</code> and <code>Amount</code> have different <code>issuer</code> values, and neither are the sender or receiver, the default path is probably not useful because it would need to ripple across a trust line between the two issuers. Ripple (the company) typically discourages issuers from trusting one another directly.</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>For cross-currency transactions, the default path uses the order book between the source currency (as specified in the <code>SendMax</code> field) and the destination currency (as specified in the <code>Amount</code> field).</li>
|
||||
</ul>
|
||||
<p>The following diagram enumerates all possible default paths:
|
||||
<a href="img/paths-default_paths.png"><img alt="Diagram of default paths" src="img/paths-default_paths.png"/></a></p>
|
||||
<p>You can use the <a href="reference-transaction-format.html#payment-flags"><code>tfNoDirectRipple</code> flag</a> to disable the default path. In this case, the transaction can only execute using the paths explicitly included in the transaction. Traders can use this option to take arbitrage opportunities.</p>
|
||||
<h2 id="path-specifications">Path Specifications</h2>
|
||||
<p>A path set is an array. Each member of the path set is another array that represents an individual <em>path</em>. Each member of a path is an object that specifies the step. A step has the following fields:</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th align="left">Field</th>
|
||||
<th align="left">Value</th>
|
||||
<th align="left">Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td align="left"><code>account</code></td>
|
||||
<td align="left">String - Address</td>
|
||||
<td align="left"><em>(Optional)</em> If present, this path step represents rippling through the specified address. MUST NOT be provided if this step specifies the <code>currency</code> or <code>issuer</code> fields.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left"><code>currency</code></td>
|
||||
<td align="left">String - Currency Code</td>
|
||||
<td align="left"><em>(Optional)</em> If present, this path step represents changing currencies through an order book. The currency specified indicates the new currency. MUST NOT be provided if this step specifies the <code>account</code> field.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left"><code>issuer</code></td>
|
||||
<td align="left">String - Address</td>
|
||||
<td align="left"><em>(Optional)</em> If present, this path step represents changing currencies and this address defines the issuer of the new currency. If omitted in a step with a non-XRP <code>currency</code>, a previous step of the path defines the issuer. If present when <code>currency</code> is omitted, indicates a path step that uses an order book between same-named currencies with different issuers. MUST be omitted if the <code>currency</code> is XRP. MUST NOT be provided if this step specifies the <code>account</code> field.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left"><code>type</code></td>
|
||||
<td align="left">Integer</td>
|
||||
<td align="left"><strong>DEPRECATED</strong> <em>(Optional)</em> An indicator of which other fields are present.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left"><code>type_hex</code></td>
|
||||
<td align="left">String</td>
|
||||
<td align="left"><strong>DEPRECATED</strong>: <em>(Optional)</em> A hexadecimal representation of the <code>type</code> field.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>In summary, the following combination of fields are valid, optionally with <code>type</code>, <code>type_hex</code>, or both:</p>
|
||||
<ul>
|
||||
<li><code>account</code> by itself</li>
|
||||
<li><code>currency</code> by itself</li>
|
||||
<li><code>currency</code> and <code>issuer</code> as long as the <code>currency</code> is not XRP</li>
|
||||
<li><code>issuer</code> by itself</li>
|
||||
</ul>
|
||||
<p>Any other use of <code>account</code>, <code>currency</code>, and <code>issuer</code> fields in a path step is invalid.</p>
|
||||
<p>The <code>type</code> field, used for the binary serialization of a path set, is actually constructed through bitwise operations on a single integer. The bits are defined as follows:</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Value (Hex)</th>
|
||||
<th>Value (Decimal)</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>0x01</td>
|
||||
<td>1</td>
|
||||
<td>A change of address (rippling): the <code>account</code> field is present.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>0x10</td>
|
||||
<td>16</td>
|
||||
<td>A change of currency: the <code>currency</code> field is present.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>0x20</td>
|
||||
<td>32</td>
|
||||
<td>A change of issuer: the <code>issuer</code> field is present.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<footer class="content-info" role="contentinfo">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-sm-12 absolute_bottom_footer">
|
||||
<div class="col-sm-8">
|
||||
<span>© 2013 - 2017 Ripple Labs, Inc. All Rights Reserved.</span>
|
||||
<span><a href="/terms-of-use/">Terms</a></span>
|
||||
<span><a href="/privacy-policy/">Privacy</a></span>
|
||||
</div>
|
||||
</div><!-- /.absolute_bottom_footer -->
|
||||
|
||||
</div><!-- /.row -->
|
||||
</div><!-- /.container -->
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,247 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<meta name="viewport" content="width=device-width">
|
||||
|
||||
<title>Reaching Consensus in the XRP Ledger - Ripple Developer Portal</title>
|
||||
|
||||
<!-- favicon -->
|
||||
<link rel="icon" href="favicon.ico" type="image/x-icon">
|
||||
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon">
|
||||
|
||||
<!-- jQuery -->
|
||||
<script src="assets/vendor/jquery-1.11.1.min.js"></script>
|
||||
|
||||
<!-- Custom Stylesheets. ripple.css includes bootstrap, font stuff -->
|
||||
<link href="assets/css/ripple.css" rel="stylesheet" />
|
||||
<link href="assets/css/devportal.css" rel="stylesheet" />
|
||||
|
||||
<!-- Bootstrap JS -->
|
||||
<script src="assets/vendor/bootstrap.min.js"></script>
|
||||
|
||||
|
||||
<!-- syntax highlighting -->
|
||||
<link rel="stylesheet" href="assets/vendor/docco.min.css" />
|
||||
<script src="assets/vendor/highlight.min.js"></script>
|
||||
|
||||
<!-- syntax selection js -->
|
||||
<script src="assets/js/multicodetab.js"></script>
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
$(".multicode").minitabs();
|
||||
hljs.initHighlighting();
|
||||
make_code_expandable();
|
||||
});
|
||||
</script>
|
||||
|
||||
<script src="assets/js/expandcode.js"></script>
|
||||
<script src="assets/js/fixsidebarscroll.js"></script>
|
||||
|
||||
<!-- fontawesome icons -->
|
||||
<link rel="stylesheet" href="assets/vendor/fontawesome/css/font-awesome.min.css" />
|
||||
|
||||
</head>
|
||||
|
||||
<body class="page page-template page-template-template-dev-portal page-template-template-dev-portal-php sidebar-primary wpb-js-composer js-comp-ver-3.6.2 vc_responsive">
|
||||
<header role="banner" class="banner navbar navbar-default navbar-fixed-top initial_header">
|
||||
<div class="container">
|
||||
<div class="navbar-header">
|
||||
<a href="index.html" class="navbar-brand"><img src="assets/img/ripple-logo-color.png" class="logo"></a>
|
||||
</div><!-- /.navbar-header -->
|
||||
<div class="nav">
|
||||
<div class="draft-warning">DRAFT PAGE</div>
|
||||
</div><!-- /.nav -->
|
||||
|
||||
</div><!-- /.container -->
|
||||
|
||||
<div class="subnav dev_nav">
|
||||
<div class="container">
|
||||
<ul id="menu-dev-menu" class="menu">
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">References <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="reference-rippleapi.html">RippleAPI</a></li>
|
||||
<li><a href="reference-rippled.html">rippled</a></li>
|
||||
<li><a href="reference-transaction-format.html">Transaction Format</a></li>
|
||||
<li><a href="reference-ledger-format.html">Ledger Format</a></li>
|
||||
<li><a href="reference-data-api.html">Ripple Data API v2</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorials <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="tutorial-multisign.html">How to Multi-Sign</a></li>
|
||||
<li><a href="tutorial-paychan.html">Payment Channels Tutorial</a></li>
|
||||
<li><a href="concept-issuing-and-operational-addresses.html">Issuing and Operational Addresses</a></li>
|
||||
<li><a href="tutorial-reliable-transaction-submission.html">Reliable Transaction Submission</a></li>
|
||||
<li><a href="tutorial-rippleapi-beginners-guide.html">RippleAPI Beginners Guide</a></li>
|
||||
<li><a href="tutorial-rippled-setup.html">rippled Setup</a></li>
|
||||
<li><a href="tutorial-gateway-guide.html">Gateway Guide</a></li>
|
||||
<li><a href="tutorial-listing-xrp.html">Listing XRP as an Exchange</a></li>
|
||||
<li><a href="tutorial-escrow.html">Escrow Tutorials</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Features <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="concept-accounts.html">Accounts</a></li>
|
||||
<li><a href="concept-amendments.html">Amendments</a></li>
|
||||
<li><a href="concept-consensus.html">Consensus Process</a></li>
|
||||
<li><a href="concept-reaching-consensus.html">Reaching Consensus in the XRP Ledger</a></li>
|
||||
<li><a href="concept-fee-voting.html">Fee Voting</a></li>
|
||||
<li><a href="concept-fees.html">Fees (Disambiguation)</a></li>
|
||||
<li><a href="concept-freeze.html">Freeze</a></li>
|
||||
<li><a href="concept-partial-payments.html">Partial Payments</a></li>
|
||||
<li><a href="concept-paths.html">Paths</a></li>
|
||||
<li><a href="concept-reserves.html">Reserves</a></li>
|
||||
<li><a href="concept-stand-alone-mode.html">Stand-Alone Mode</a></li>
|
||||
<li><a href="concept-transaction-cost.html">Transaction Cost</a></li>
|
||||
<li><a href="concept-transfer-fees.html">Transfer Fees</a></li>
|
||||
<li><a href="concept-noripple.html">Understanding the NoRipple flag</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Gateway Bulletins <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="gb-2015-06.html">GB-2015-06: Corrections to Autobridging</a></li>
|
||||
<li><a href="gb-2015-05.html">GB-2015-05: Historical Ledger Query Migration</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">API Tools <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="ripple-api-tool.html">WebSocket API Tool</a></li>
|
||||
<li><a href="data-api-v2-tool.html">Data API v2 Tool</a></li>
|
||||
<li><a href="tool-jsonrpc.html">rippled JSON-RPC Tool</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li><a href="https://github.com/ripple/ripple-dev-portal" title="GitHub">Site Source</a></li>
|
||||
</ul><!-- /#dev-menu -->
|
||||
</div><!-- /.subnav .container -->
|
||||
</div><!-- /.subnav -->
|
||||
</header>
|
||||
|
||||
|
||||
<div class="wrap container" role="document">
|
||||
<aside class="sidebar" role="complementary">
|
||||
<div class="dev_nav_wrapper">
|
||||
<div id="cont">
|
||||
<h5>In this category:</h5>
|
||||
<ul class="dev_nav_sidebar">
|
||||
<li class="level-1"><a href="index.html">Category: Features</a></li>
|
||||
<li class="level-2"><a href="concept-accounts.html">Accounts</a></li>
|
||||
<li class="level-2"><a href="concept-amendments.html">Amendments</a></li>
|
||||
<li class="level-2"><a href="concept-consensus.html">Consensus Process</a></li>
|
||||
<li class="level-2"><a href="concept-reaching-consensus.html">Reaching Consensus in the XRP Ledger</a></li>
|
||||
<li class="level-2"><a href="concept-fee-voting.html">Fee Voting</a></li>
|
||||
<li class="level-2"><a href="concept-fees.html">Fees (Disambiguation)</a></li>
|
||||
<li class="level-2"><a href="concept-freeze.html">Freeze</a></li>
|
||||
<li class="level-2"><a href="concept-partial-payments.html">Partial Payments</a></li>
|
||||
<li class="level-2"><a href="concept-paths.html">Paths</a></li>
|
||||
<li class="level-2"><a href="concept-reserves.html">Reserves</a></li>
|
||||
<li class="level-2"><a href="concept-stand-alone-mode.html">Stand-Alone Mode</a></li>
|
||||
<li class="level-2"><a href="concept-transaction-cost.html">Transaction Cost</a></li>
|
||||
<li class="level-2"><a href="concept-transfer-fees.html">Transfer Fees</a></li>
|
||||
<li class="level-2"><a href="concept-noripple.html">Understanding the NoRipple flag</a></li>
|
||||
</ul>
|
||||
<hr />
|
||||
<h5>In this page:</h5>
|
||||
<ul class="dev_nav_sidebar" id="dactyl_toc_sidebar">
|
||||
<li class="level-1"><a href="#reaching-consensus-in-the-xrp-ledger">Reaching Consensus in the XRP Ledger</a></li>
|
||||
<li class="level-1"><a href="#background">Background</a></li>
|
||||
<li class="level-2"><a href="#mechanics">Mechanics</a></li>
|
||||
<li class="level-2"><a href="#the-double-spend-problem">The Double Spend Problem</a></li>
|
||||
<li class="level-1"><a href="#how-consensus-works">How Consensus Works</a></li>
|
||||
<li class="level-2"><a href="#simplfying-the-problem">Simplfying the Problem</a></li>
|
||||
<li class="level-2"><a href="#consensus-rules">Consensus Rules</a></li>
|
||||
<li class="level-2"><a href="#consensus-rounds">Consensus Rounds</a></li>
|
||||
<li class="level-2"><a href="#consensus-can-fail">Consensus Can Fail</a></li>
|
||||
<li class="level-2"><a href="#how-the-xrp-ledger-handles-consensus-failure">How the XRP Ledger Handles Consensus Failure</a></li>
|
||||
<li class="level-1"><a href="#philosophy">Philosophy</a></li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
<main class="main" role="main">
|
||||
<div class='content'>
|
||||
<h1 id="reaching-consensus-in-the-xrp-ledger">Reaching Consensus in the XRP Ledger</h1>
|
||||
<p>The XRP Ledger is a universal payment system enabling users to transfer funds (including fiat currencies, digital currencies and other forms of value) across national boundaries as seamlessly as sending an email. Like other digital currencies 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 also allows users to transact in currencies other than the ledger's native currency, XRP. In addition, the technology enables near real-time settlement (three to six seconds) and is built to route each international transaction to the cheapest FX bid/ask spread available in the network.</p>
|
||||
<h1 id="background">Background</h1>
|
||||
<h2 id="mechanics">Mechanics</h2>
|
||||
<p>At the core, the XRP Ledger is a shared database that records information such as accounts, balances, and offers to trade assets. Operations such as creating accounts, making payments, and converting assets are performed through signed instructions called “transactions.”</p>
|
||||
<p>As a cryptographic system, the owners of XRP Ledger accounts are identified by cryptographic identities. 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 an identical, complete copy of the ledger state, without needing a single central authority to arbitrate transactions.</p>
|
||||
<h2 id="the-double-spend-problem">The Double Spend Problem</h2>
|
||||
<p>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.</p>
|
||||
<p>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.</p>
|
||||
<p>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.</p>
|
||||
<p>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 deck 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.</p>
|
||||
<p>Distributed ledger technologies, like the XRP Ledger, have no central authority. They must solve the double spend problem in some other way.</p>
|
||||
<h1 id="how-consensus-works">How Consensus Works</h1>
|
||||
<h2 id="simplfying-the-problem">Simplfying the Problem</h2>
|
||||
<p>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.</p>
|
||||
<p>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.</p>
|
||||
<p>We can also order transactions by deterministic rules. Because transactions are collections of digital information, it's trivial for a computer to sort them.</p>
|
||||
<p>This would be sufficient 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. Obviously, this is impractical.</p>
|
||||
<p>However, if we could collect transactions into groups and agree on those groupings, we could sort the transactions within that group. That is, so 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 simply 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.</p>
|
||||
<p>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.</p>
|
||||
<h2 id="consensus-rules">Consensus Rules</h2>
|
||||
<p>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:</p>
|
||||
<ol>
|
||||
<li>If there is no reason a transaction should not be included in such a group of transactions, all honest participants will agree to include it. If all participants already agree, consensus has no work to do.</li>
|
||||
<li>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.</li>
|
||||
<li>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.</li>
|
||||
<li>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.</li>
|
||||
</ol>
|
||||
<p>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 to be processed). However, every honest participant’s second priority is agreement. A network with possible double spends has no utility at all. Agreement is facilitated by the fact that every honest participant values it above everything but correctness.</p>
|
||||
<h2 id="consensus-rounds">Consensus Rounds</h2>
|
||||
<p>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 witnessed.</p>
|
||||
<p>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.</p>
|
||||
<p>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.</p>
|
||||
<p>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.</p>
|
||||
<h2 id="consensus-can-fail">Consensus Can Fail</h2>
|
||||
<p>It is not practical to develop a consensus algorithm that never fails to achieve perfect consensus. To understand why, consider how the consensus process terminates. 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.</p>
|
||||
<p>Clearly, 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.</p>
|
||||
<p>In other words, for the consensus process to ever terminate, 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.</p>
|
||||
<p>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, <em>someone</em> 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.</p>
|
||||
<p>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.</p>
|
||||
<h2 id="how-the-xrp-ledger-handles-consensus-failure">How the XRP Ledger Handles Consensus Failure</h2>
|
||||
<p>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.</p>
|
||||
<p>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.</p>
|
||||
<p>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.</p>
|
||||
<p>Participants then find themselves in one of three cases, in order of probability:</p>
|
||||
<ol>
|
||||
<li>They built the same ledger a supermajority agreed to. In this case, they can consider that ledger fully validated and rely on its contents.</li>
|
||||
<li>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.</li>
|
||||
<li>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.</li>
|
||||
</ol>
|
||||
<p>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 operate 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.</p>
|
||||
<p>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 subsequent consensus round is much less likely to fail because disagreements are resolved in the consensus process and only remaining disagreements can cause a failure.</p>
|
||||
<p>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.</p>
|
||||
<h1 id="philosophy">Philosophy</h1>
|
||||
<p>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.</p>
|
||||
<p>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.</p>
|
||||
<p>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.</p>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<footer class="content-info" role="contentinfo">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-sm-12 absolute_bottom_footer">
|
||||
<div class="col-sm-8">
|
||||
<span>© 2013 - 2017 Ripple Labs, Inc. All Rights Reserved.</span>
|
||||
<span><a href="/terms-of-use/">Terms</a></span>
|
||||
<span><a href="/privacy-policy/">Privacy</a></span>
|
||||
</div>
|
||||
</div><!-- /.absolute_bottom_footer -->
|
||||
|
||||
</div><!-- /.row -->
|
||||
</div><!-- /.container -->
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,211 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<meta name="viewport" content="width=device-width">
|
||||
|
||||
<title>Reserves - Ripple Developer Portal</title>
|
||||
|
||||
<!-- favicon -->
|
||||
<link rel="icon" href="favicon.ico" type="image/x-icon">
|
||||
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon">
|
||||
|
||||
<!-- jQuery -->
|
||||
<script src="assets/vendor/jquery-1.11.1.min.js"></script>
|
||||
|
||||
<!-- Custom Stylesheets. ripple.css includes bootstrap, font stuff -->
|
||||
<link href="assets/css/ripple.css" rel="stylesheet" />
|
||||
<link href="assets/css/devportal.css" rel="stylesheet" />
|
||||
|
||||
<!-- Bootstrap JS -->
|
||||
<script src="assets/vendor/bootstrap.min.js"></script>
|
||||
|
||||
|
||||
<!-- syntax highlighting -->
|
||||
<link rel="stylesheet" href="assets/vendor/docco.min.css" />
|
||||
<script src="assets/vendor/highlight.min.js"></script>
|
||||
|
||||
<!-- syntax selection js -->
|
||||
<script src="assets/js/multicodetab.js"></script>
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
$(".multicode").minitabs();
|
||||
hljs.initHighlighting();
|
||||
make_code_expandable();
|
||||
});
|
||||
</script>
|
||||
|
||||
<script src="assets/js/expandcode.js"></script>
|
||||
<script src="assets/js/fixsidebarscroll.js"></script>
|
||||
|
||||
<!-- fontawesome icons -->
|
||||
<link rel="stylesheet" href="assets/vendor/fontawesome/css/font-awesome.min.css" />
|
||||
|
||||
</head>
|
||||
|
||||
<body class="page page-template page-template-template-dev-portal page-template-template-dev-portal-php sidebar-primary wpb-js-composer js-comp-ver-3.6.2 vc_responsive">
|
||||
<header role="banner" class="banner navbar navbar-default navbar-fixed-top initial_header">
|
||||
<div class="container">
|
||||
<div class="navbar-header">
|
||||
<a href="index.html" class="navbar-brand"><img src="assets/img/ripple-logo-color.png" class="logo"></a>
|
||||
</div><!-- /.navbar-header -->
|
||||
<div class="nav">
|
||||
<div class="draft-warning">DRAFT PAGE</div>
|
||||
</div><!-- /.nav -->
|
||||
|
||||
</div><!-- /.container -->
|
||||
|
||||
<div class="subnav dev_nav">
|
||||
<div class="container">
|
||||
<ul id="menu-dev-menu" class="menu">
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">References <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="reference-rippleapi.html">RippleAPI</a></li>
|
||||
<li><a href="reference-rippled.html">rippled</a></li>
|
||||
<li><a href="reference-transaction-format.html">Transaction Format</a></li>
|
||||
<li><a href="reference-ledger-format.html">Ledger Format</a></li>
|
||||
<li><a href="reference-data-api.html">Ripple Data API v2</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorials <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="tutorial-multisign.html">How to Multi-Sign</a></li>
|
||||
<li><a href="tutorial-paychan.html">Payment Channels Tutorial</a></li>
|
||||
<li><a href="concept-issuing-and-operational-addresses.html">Issuing and Operational Addresses</a></li>
|
||||
<li><a href="tutorial-reliable-transaction-submission.html">Reliable Transaction Submission</a></li>
|
||||
<li><a href="tutorial-rippleapi-beginners-guide.html">RippleAPI Beginners Guide</a></li>
|
||||
<li><a href="tutorial-rippled-setup.html">rippled Setup</a></li>
|
||||
<li><a href="tutorial-gateway-guide.html">Gateway Guide</a></li>
|
||||
<li><a href="tutorial-listing-xrp.html">Listing XRP as an Exchange</a></li>
|
||||
<li><a href="tutorial-escrow.html">Escrow Tutorials</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Features <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="concept-accounts.html">Accounts</a></li>
|
||||
<li><a href="concept-amendments.html">Amendments</a></li>
|
||||
<li><a href="concept-consensus.html">Consensus Process</a></li>
|
||||
<li><a href="concept-reaching-consensus.html">Reaching Consensus in the XRP Ledger</a></li>
|
||||
<li><a href="concept-fee-voting.html">Fee Voting</a></li>
|
||||
<li><a href="concept-fees.html">Fees (Disambiguation)</a></li>
|
||||
<li><a href="concept-freeze.html">Freeze</a></li>
|
||||
<li><a href="concept-partial-payments.html">Partial Payments</a></li>
|
||||
<li><a href="concept-paths.html">Paths</a></li>
|
||||
<li><a href="concept-reserves.html">Reserves</a></li>
|
||||
<li><a href="concept-stand-alone-mode.html">Stand-Alone Mode</a></li>
|
||||
<li><a href="concept-transaction-cost.html">Transaction Cost</a></li>
|
||||
<li><a href="concept-transfer-fees.html">Transfer Fees</a></li>
|
||||
<li><a href="concept-noripple.html">Understanding the NoRipple flag</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Gateway Bulletins <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="gb-2015-06.html">GB-2015-06: Corrections to Autobridging</a></li>
|
||||
<li><a href="gb-2015-05.html">GB-2015-05: Historical Ledger Query Migration</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">API Tools <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="ripple-api-tool.html">WebSocket API Tool</a></li>
|
||||
<li><a href="data-api-v2-tool.html">Data API v2 Tool</a></li>
|
||||
<li><a href="tool-jsonrpc.html">rippled JSON-RPC Tool</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li><a href="https://github.com/ripple/ripple-dev-portal" title="GitHub">Site Source</a></li>
|
||||
</ul><!-- /#dev-menu -->
|
||||
</div><!-- /.subnav .container -->
|
||||
</div><!-- /.subnav -->
|
||||
</header>
|
||||
|
||||
|
||||
<div class="wrap container" role="document">
|
||||
<aside class="sidebar" role="complementary">
|
||||
<div class="dev_nav_wrapper">
|
||||
<div id="cont">
|
||||
<h5>In this category:</h5>
|
||||
<ul class="dev_nav_sidebar">
|
||||
<li class="level-1"><a href="index.html">Category: Features</a></li>
|
||||
<li class="level-2"><a href="concept-accounts.html">Accounts</a></li>
|
||||
<li class="level-2"><a href="concept-amendments.html">Amendments</a></li>
|
||||
<li class="level-2"><a href="concept-consensus.html">Consensus Process</a></li>
|
||||
<li class="level-2"><a href="concept-reaching-consensus.html">Reaching Consensus in the XRP Ledger</a></li>
|
||||
<li class="level-2"><a href="concept-fee-voting.html">Fee Voting</a></li>
|
||||
<li class="level-2"><a href="concept-fees.html">Fees (Disambiguation)</a></li>
|
||||
<li class="level-2"><a href="concept-freeze.html">Freeze</a></li>
|
||||
<li class="level-2"><a href="concept-partial-payments.html">Partial Payments</a></li>
|
||||
<li class="level-2"><a href="concept-paths.html">Paths</a></li>
|
||||
<li class="level-2"><a href="concept-reserves.html">Reserves</a></li>
|
||||
<li class="level-2"><a href="concept-stand-alone-mode.html">Stand-Alone Mode</a></li>
|
||||
<li class="level-2"><a href="concept-transaction-cost.html">Transaction Cost</a></li>
|
||||
<li class="level-2"><a href="concept-transfer-fees.html">Transfer Fees</a></li>
|
||||
<li class="level-2"><a href="concept-noripple.html">Understanding the NoRipple flag</a></li>
|
||||
</ul>
|
||||
<hr />
|
||||
<h5>In this page:</h5>
|
||||
<ul class="dev_nav_sidebar" id="dactyl_toc_sidebar">
|
||||
<li class="level-1"><a href="#reserves">Reserves</a></li>
|
||||
<li class="level-2"><a href="#base-reserve-and-owner-reserve">Base Reserve and Owner Reserve</a></li>
|
||||
<li class="level-3"><a href="#owner-reserves">Owner Reserves</a></li>
|
||||
<li class="level-2"><a href="#going-below-the-reserve-requirement">Going Below the Reserve Requirement</a></li>
|
||||
<li class="level-2"><a href="#changing-the-reserve-requirements">Changing the Reserve Requirements</a></li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
<main class="main" role="main">
|
||||
<div class='content'>
|
||||
<h1 id="reserves">Reserves</h1>
|
||||
<p>The XRP Ledger applies <em>reserve requirements</em>, 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 and the full ledger history on disk.</p>
|
||||
<p>To submit transactions, 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 enough XRP to meet the reserve requirement.</p>
|
||||
<p>The current minimum reserve requirement is <strong>20 XRP</strong>. (This is the cost of an address that owns no other objects in the ledger.)</p>
|
||||
<h2 id="base-reserve-and-owner-reserve">Base Reserve and Owner Reserve</h2>
|
||||
<p>The reserve requirement is divided into two parts:</p>
|
||||
<ul>
|
||||
<li>The <strong>Base Reserve</strong> is a minimum amount of XRP that is required for every address in the ledger. Currently, this is 20 XRP (<code>20000000</code> drops).</li>
|
||||
<li>The <strong>Owner Reserve</strong> is an increase to the reserve requirement for each object that the address owns in the ledger. Currently, this is 5 XRP (<code>5000000</code> drops) per item.</li>
|
||||
</ul>
|
||||
<h3 id="owner-reserves">Owner Reserves</h3>
|
||||
<p>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.</p>
|
||||
<ul>
|
||||
<li><a href="reference-ledger-format.html#offer">Offers</a> 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 <a href="reference-transaction-format.html#offercancel">OfferCancel transaction</a>, or by sending an <a href="reference-transaction-format.html#offercreate">OfferCreate transaction</a> that contains an <code>OfferSequence</code> parameter.</li>
|
||||
<li><a href="reference-ledger-format.html#ripplestate">Trust lines</a> 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. See <a href="reference-ledger-format.html#contributing-to-the-owner-reserve">Contributing to the Owner Reserve</a> for details.</li>
|
||||
<li>A single <a href="reference-ledger-format.html#signerlist">SignerList</a> counts as 3 to 10 objects for purposes of the owner reserve, depending on how many members it has. See also: <a href="reference-ledger-format.html#signerlists-and-reserves">SignerLists and Reserves</a>.</li>
|
||||
<li><a href="reference-ledger-format.html#escrow">Held Payments (Escrow)</a> are owned by the address that placed them.</li>
|
||||
<li><a href="reference-ledger-format.html#directorynode">Owner directories</a> list all the ledger nodes that contribute to an address's owner reserve. However, the owner directory itself does not count towards the reserve.</li>
|
||||
</ul>
|
||||
<h4 id="owner-reserve-edge-cases">Owner Reserve Edge Cases</h4>
|
||||
<p>The XRP Ledger considers an <a href="reference-transaction-format.html#offercreate">OfferCreate transaction</a> 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 <code>taker_pays</code> 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: <a href="reference-transaction-format.html#lifecycle-of-an-offer">Lifecycle of an Offer</a>.</p>
|
||||
<h2 id="going-below-the-reserve-requirement">Going Below the Reserve Requirement</h2>
|
||||
<p>During transaction processing, the <a href="concept-transaction-cost.html">transaction cost</a> destroys some of the sending address's XRP balance. This can cause an address's XRP to go below the reserve requirement.</p>
|
||||
<p>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 <a href="#changing-the-reserve-requirements">reserve requirement decreases</a> to less than the address's XRP holdings.</p>
|
||||
<p class="devportal-callout tip"><strong>Tip:</strong> When an address is below the reserve requirement, it can send new <a href="reference-transaction-format.html#offercreate">OfferCreate transactions</a> to acquire more XRP, or other currencies on its existing trust lines. These transactions cannot create new <a href="reference-ledger-format.html#ripplestate">trust lines</a>, or <a href="reference-ledger-format.html#offer">Offer nodes in the ledger</a>, so they can only execute trades that consume Offers that are already in the order books.</p>
|
||||
<h2 id="changing-the-reserve-requirements">Changing the Reserve Requirements</h2>
|
||||
<p>The XRP Ledger has a mechanism to adjust the reserve requirements for long-term changes in the value of XRP. Any changes have to be approved by the consensus process. See <a href="concept-fee-voting.html">Fee Voting</a> for more information.</p>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<footer class="content-info" role="contentinfo">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-sm-12 absolute_bottom_footer">
|
||||
<div class="col-sm-8">
|
||||
<span>© 2013 - 2017 Ripple Labs, Inc. All Rights Reserved.</span>
|
||||
<span><a href="/terms-of-use/">Terms</a></span>
|
||||
<span><a href="/privacy-policy/">Privacy</a></span>
|
||||
</div>
|
||||
</div><!-- /.absolute_bottom_footer -->
|
||||
|
||||
</div><!-- /.row -->
|
||||
</div><!-- /.container -->
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,249 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<meta name="viewport" content="width=device-width">
|
||||
|
||||
<title>Stand-Alone Mode - Ripple Developer Portal</title>
|
||||
|
||||
<!-- favicon -->
|
||||
<link rel="icon" href="favicon.ico" type="image/x-icon">
|
||||
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon">
|
||||
|
||||
<!-- jQuery -->
|
||||
<script src="assets/vendor/jquery-1.11.1.min.js"></script>
|
||||
|
||||
<!-- Custom Stylesheets. ripple.css includes bootstrap, font stuff -->
|
||||
<link href="assets/css/ripple.css" rel="stylesheet" />
|
||||
<link href="assets/css/devportal.css" rel="stylesheet" />
|
||||
|
||||
<!-- Bootstrap JS -->
|
||||
<script src="assets/vendor/bootstrap.min.js"></script>
|
||||
|
||||
|
||||
<!-- syntax highlighting -->
|
||||
<link rel="stylesheet" href="assets/vendor/docco.min.css" />
|
||||
<script src="assets/vendor/highlight.min.js"></script>
|
||||
|
||||
<!-- syntax selection js -->
|
||||
<script src="assets/js/multicodetab.js"></script>
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
$(".multicode").minitabs();
|
||||
hljs.initHighlighting();
|
||||
make_code_expandable();
|
||||
});
|
||||
</script>
|
||||
|
||||
<script src="assets/js/expandcode.js"></script>
|
||||
<script src="assets/js/fixsidebarscroll.js"></script>
|
||||
|
||||
<!-- fontawesome icons -->
|
||||
<link rel="stylesheet" href="assets/vendor/fontawesome/css/font-awesome.min.css" />
|
||||
|
||||
</head>
|
||||
|
||||
<body class="page page-template page-template-template-dev-portal page-template-template-dev-portal-php sidebar-primary wpb-js-composer js-comp-ver-3.6.2 vc_responsive">
|
||||
<header role="banner" class="banner navbar navbar-default navbar-fixed-top initial_header">
|
||||
<div class="container">
|
||||
<div class="navbar-header">
|
||||
<a href="index.html" class="navbar-brand"><img src="assets/img/ripple-logo-color.png" class="logo"></a>
|
||||
</div><!-- /.navbar-header -->
|
||||
<div class="nav">
|
||||
<div class="draft-warning">DRAFT PAGE</div>
|
||||
</div><!-- /.nav -->
|
||||
|
||||
</div><!-- /.container -->
|
||||
|
||||
<div class="subnav dev_nav">
|
||||
<div class="container">
|
||||
<ul id="menu-dev-menu" class="menu">
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">References <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="reference-rippleapi.html">RippleAPI</a></li>
|
||||
<li><a href="reference-rippled.html">rippled</a></li>
|
||||
<li><a href="reference-transaction-format.html">Transaction Format</a></li>
|
||||
<li><a href="reference-ledger-format.html">Ledger Format</a></li>
|
||||
<li><a href="reference-data-api.html">Ripple Data API v2</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorials <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="tutorial-multisign.html">How to Multi-Sign</a></li>
|
||||
<li><a href="tutorial-paychan.html">Payment Channels Tutorial</a></li>
|
||||
<li><a href="concept-issuing-and-operational-addresses.html">Issuing and Operational Addresses</a></li>
|
||||
<li><a href="tutorial-reliable-transaction-submission.html">Reliable Transaction Submission</a></li>
|
||||
<li><a href="tutorial-rippleapi-beginners-guide.html">RippleAPI Beginners Guide</a></li>
|
||||
<li><a href="tutorial-rippled-setup.html">rippled Setup</a></li>
|
||||
<li><a href="tutorial-gateway-guide.html">Gateway Guide</a></li>
|
||||
<li><a href="tutorial-listing-xrp.html">Listing XRP as an Exchange</a></li>
|
||||
<li><a href="tutorial-escrow.html">Escrow Tutorials</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Features <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="concept-accounts.html">Accounts</a></li>
|
||||
<li><a href="concept-amendments.html">Amendments</a></li>
|
||||
<li><a href="concept-consensus.html">Consensus Process</a></li>
|
||||
<li><a href="concept-reaching-consensus.html">Reaching Consensus in the XRP Ledger</a></li>
|
||||
<li><a href="concept-fee-voting.html">Fee Voting</a></li>
|
||||
<li><a href="concept-fees.html">Fees (Disambiguation)</a></li>
|
||||
<li><a href="concept-freeze.html">Freeze</a></li>
|
||||
<li><a href="concept-partial-payments.html">Partial Payments</a></li>
|
||||
<li><a href="concept-paths.html">Paths</a></li>
|
||||
<li><a href="concept-reserves.html">Reserves</a></li>
|
||||
<li><a href="concept-stand-alone-mode.html">Stand-Alone Mode</a></li>
|
||||
<li><a href="concept-transaction-cost.html">Transaction Cost</a></li>
|
||||
<li><a href="concept-transfer-fees.html">Transfer Fees</a></li>
|
||||
<li><a href="concept-noripple.html">Understanding the NoRipple flag</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Gateway Bulletins <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="gb-2015-06.html">GB-2015-06: Corrections to Autobridging</a></li>
|
||||
<li><a href="gb-2015-05.html">GB-2015-05: Historical Ledger Query Migration</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">API Tools <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="ripple-api-tool.html">WebSocket API Tool</a></li>
|
||||
<li><a href="data-api-v2-tool.html">Data API v2 Tool</a></li>
|
||||
<li><a href="tool-jsonrpc.html">rippled JSON-RPC Tool</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li><a href="https://github.com/ripple/ripple-dev-portal" title="GitHub">Site Source</a></li>
|
||||
</ul><!-- /#dev-menu -->
|
||||
</div><!-- /.subnav .container -->
|
||||
</div><!-- /.subnav -->
|
||||
</header>
|
||||
|
||||
|
||||
<div class="wrap container" role="document">
|
||||
<aside class="sidebar" role="complementary">
|
||||
<div class="dev_nav_wrapper">
|
||||
<div id="cont">
|
||||
<h5>In this category:</h5>
|
||||
<ul class="dev_nav_sidebar">
|
||||
<li class="level-1"><a href="index.html">Category: Features</a></li>
|
||||
<li class="level-2"><a href="concept-accounts.html">Accounts</a></li>
|
||||
<li class="level-2"><a href="concept-amendments.html">Amendments</a></li>
|
||||
<li class="level-2"><a href="concept-consensus.html">Consensus Process</a></li>
|
||||
<li class="level-2"><a href="concept-reaching-consensus.html">Reaching Consensus in the XRP Ledger</a></li>
|
||||
<li class="level-2"><a href="concept-fee-voting.html">Fee Voting</a></li>
|
||||
<li class="level-2"><a href="concept-fees.html">Fees (Disambiguation)</a></li>
|
||||
<li class="level-2"><a href="concept-freeze.html">Freeze</a></li>
|
||||
<li class="level-2"><a href="concept-partial-payments.html">Partial Payments</a></li>
|
||||
<li class="level-2"><a href="concept-paths.html">Paths</a></li>
|
||||
<li class="level-2"><a href="concept-reserves.html">Reserves</a></li>
|
||||
<li class="level-2"><a href="concept-stand-alone-mode.html">Stand-Alone Mode</a></li>
|
||||
<li class="level-2"><a href="concept-transaction-cost.html">Transaction Cost</a></li>
|
||||
<li class="level-2"><a href="concept-transfer-fees.html">Transfer Fees</a></li>
|
||||
<li class="level-2"><a href="concept-noripple.html">Understanding the NoRipple flag</a></li>
|
||||
</ul>
|
||||
<hr />
|
||||
<h5>In this page:</h5>
|
||||
<ul class="dev_nav_sidebar" id="dactyl_toc_sidebar">
|
||||
<li class="level-1"><a href="#stand-alone-mode">Stand-Alone Mode</a></li>
|
||||
<li class="level-2"><a href="#new-genesis-ledger">New Genesis Ledger</a></li>
|
||||
<li class="level-2"><a href="#load-saved-ledger">Load Saved Ledger</a></li>
|
||||
<li class="level-3"><a href="#1-start-rippled-normally">1. Start rippled normally.</a></li>
|
||||
<li class="level-3"><a href="#2-wait-until-rippled-is-synced">2. Wait until rippled is synced.</a></li>
|
||||
<li class="level-3"><a href="#3-optional-retrieve-specific-ledger-versions">3. (Optional) Retrieve specific ledger versions.</a></li>
|
||||
<li class="level-3"><a href="#4-shut-down-rippled">4. Shut down rippled .</a></li>
|
||||
<li class="level-3"><a href="#5-start-rippled-in-stand-alone-mode">5. Start rippled in stand-alone mode.</a></li>
|
||||
<li class="level-3"><a href="#6-manually-advance-the-ledger">6. Manually advance the ledger.</a></li>
|
||||
<li class="level-2"><a href="#advancing-ledgers-in-stand-alone-mode">Advancing Ledgers in Stand-Alone Mode</a></li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
<main class="main" role="main">
|
||||
<div class='content'>
|
||||
<h1 id="stand-alone-mode">Stand-Alone Mode</h1>
|
||||
<p>You can run <code>rippled</code> in stand-alone mode without a consensus of trusted servers. In stand-alone mode, <code>rippled</code> does not communicate with any other servers in the XRP Ledger peer-to-peer network, but you can do most of the same actions on your local server only. Stand-alone provides a method for testing <code>rippled</code> behavior without being tied to the live network. For example, you can <a href="concept-amendments.html#testing-amendments">test the effects of Amendments</a> before those Amendments have gone into effect across the decentralized network.</p>
|
||||
<p>When you run <code>rippled</code> in stand-alone mode, you have to tell it what ledger version to start from:</p>
|
||||
<ul>
|
||||
<li>Create a <a href="#new-genesis-ledger">new genesis ledger</a> from scratch.</li>
|
||||
<li><a href="#load-saved-ledger">Load an existing ledger version</a> from disk.</li>
|
||||
</ul>
|
||||
<p class="devportal-callout caution"><strong>Caution:</strong> In stand-alone mode, you must <a href="#advancing-ledgers-in-stand-alone-mode">manually advance the ledger</a>.</p>
|
||||
<h2 id="new-genesis-ledger">New Genesis Ledger</h2>
|
||||
<p>In stand-alone mode, you can have <code>rippled</code> create a new genesis ledger. This provides a known state, with none of the ledger history from the production XRP Ledger. (This is very useful for unit tests, among other things.)</p>
|
||||
<ul>
|
||||
<li>To start <code>rippled</code> in stand-alone mode with a new genesis ledger, use the <a href="https://wiki.ripple.com/Rippled#--standalone.2C_-a"><code>-a</code></a> and <a href="https://wiki.ripple.com/Rippled#--start"><code>--start</code></a> options:</li>
|
||||
</ul>
|
||||
<pre><code>rippled -a --start --conf=/path/to/rippled.cfg
|
||||
</code></pre>
|
||||
<p>In a genesis ledger, the <a href="concept-accounts.html#special-addresses">genesis address</a> holds all 100 billion XRP. The keys of the genesis address are <a href="https://github.com/ripple/rippled/blob/94ed5b3a53077d815ad0dd65d490c8d37a147361/src/ripple/app/ledger/Ledger.cpp#L184">hardcoded</a> as follows:</p>
|
||||
<p><strong>Address:</strong> <code>rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh</code></p>
|
||||
<p><strong>Secret:</strong> <code>snoPBrXtMeMyMHUVTgbuqAfg1SUTb</code> ("masterpassphrase")</p>
|
||||
<p class="devportal-callout caution"><strong>Caution:</strong> If you create a new genesis ledger, the hard-coded default <a href="concept-reserves.html">Reserve</a> is <strong>200 XRP</strong> minimum for funding a new address, with an increment of <strong>50 XRP</strong> per object in the ledger. These values are higher than the current reserve requirements of the production network. (See also: <a href="concept-fee-voting.html">Fee Voting</a>)</p>
|
||||
<p><a href="https://github.com/ripple/rippled/releases/tag/0.50.0" title="New in: rippled 0.50.0"><img alt="New in: rippled 0.50.0" class="dactyl_badge" src="https://img.shields.io/badge/New%20in-rippled%200.50.0-blue.svg"/></a> If you start a new genesis ledger with <code>--start</code>, all The genesis ledger contains an <a href="reference-transaction-format.html#enableamendment">EnableAmendment pseudo-transaction</a> to turn on all <a href="concept-amendments.html">Amendments</a> natively supported by the <code>rippled</code> server, except for amendments that you explicitly disable in the configuration file. The effects of those amendments are available starting from the very next ledger version.</p>
|
||||
<h2 id="load-saved-ledger">Load Saved Ledger</h2>
|
||||
<p>You can start with a ledger version that was saved to disk if your <code>rippled</code> server was previously synced with the XRP Ledger peer-to-peer network (either the production network or the <a href="tutorial-rippled-setup.html#parallel-networks">Test Net</a>).</p>
|
||||
<h3 id="1-start-rippled-normally">1. Start <code>rippled</code> normally.</h3>
|
||||
<p>To load an existing ledger, you must first retrieve that ledger from the network. Start <code>rippled</code> in online mode as normal:</p>
|
||||
<pre><code>rippled --conf=/path/to/rippled.cfg
|
||||
</code></pre>
|
||||
<h3 id="2-wait-until-rippled-is-synced">2. Wait until <code>rippled</code> is synced.</h3>
|
||||
<p>Use the <a href="reference-rippled.html#server-info"><code>server_info</code> command</a> to check the state of your server relative to the network. Your server is synced when the <code>server_state</code> value shows any of the following values:</p>
|
||||
<ul>
|
||||
<li><code>full</code></li>
|
||||
<li><code>proposing</code></li>
|
||||
<li><code>validating</code></li>
|
||||
</ul>
|
||||
<p>For more information, see <a href="reference-rippled.html#possible-server-states">Possible Server States</a>.</p>
|
||||
<h3 id="3-optional-retrieve-specific-ledger-versions">3. (Optional) Retrieve specific ledger versions.</h3>
|
||||
<p>If you only want the most recent ledger, you can skip this step.</p>
|
||||
<p>If you want to load a specific historical ledger version, use the <a href="reference-rippled.html#ledger-request"><code>ledger_request</code> command</a> to make <code>rippled</code> fetch it. If <code>rippled</code> does not already have the ledger version, you may have to run the <code>ledger_request</code> command multiple times until it has finished retrieving the ledger.</p>
|
||||
<p>If you want to replay a specific historical ledger version, you must fetch both the ledger version to replay and the ledger version before it. (The previous ledger version sets up the initial state upon which you apply the changes described by the ledger version you replay.)</p>
|
||||
<h3 id="4-shut-down-rippled">4. Shut down <code>rippled</code>.</h3>
|
||||
<p>Use the <a href="reference-rippled.html#stop"><code>stop</code> command</a>:</p>
|
||||
<pre><code>rippled stop --conf=/path/to/rippled.cfg
|
||||
</code></pre>
|
||||
<h3 id="5-start-rippled-in-stand-alone-mode">5. Start <code>rippled</code> in stand-alone mode.</h3>
|
||||
<p>To load the most recent ledger version, you can use the <a href="https://wiki.ripple.com/Rippled#--standalone.2C_-a"><code>-a</code></a> and <a href="https://wiki.ripple.com/Rippled#--load"><code>--load</code></a> options when starting the server:</p>
|
||||
<pre><code>rippled -a --load --conf=/path/to/rippled.cfg
|
||||
</code></pre>
|
||||
<p>To instead load a specific historical ledger, use the <a href="https://wiki.ripple.com/Rippled#--load"><code>--load</code></a> parameter along with the <code>--ledger</code> parameter, providing the ledger index or identifying hash of the ledger version to load:</p>
|
||||
<pre><code>rippled -a --load --ledger 19860944 --conf=/path/to/rippled.cfg
|
||||
</code></pre>
|
||||
<h3 id="6-manually-advance-the-ledger">6. Manually advance the ledger.</h3>
|
||||
<p>When you load a ledger with <code>--ledger</code> in stand-alone mode, it goes to the current open ledger, so you must <a href="#advancing-ledgers-in-stand-alone-mode">manually advance the ledger</a>:</p>
|
||||
<pre><code>rippled ledger_accept --conf=/path/to/rippled.cfg
|
||||
</code></pre>
|
||||
<h2 id="advancing-ledgers-in-stand-alone-mode">Advancing Ledgers in Stand-Alone Mode</h2>
|
||||
<p>In stand-alone mode, <code>rippled</code> does not communicate to other members of the peer-to-peer network or participate in a consensus process. Instead, you must manually advance the ledger index using the <a href="reference-rippled.html#ledger-accept"><code>ledger_accept</code> command</a>:</p>
|
||||
<pre><code>rippled ledger_accept --conf=/path/to/rippled.cfg
|
||||
</code></pre>
|
||||
<p>In stand-alone mode, <code>rippled</code> makes no distinction between a "closed" ledger version and a "validated" ledger version. (For more information about the difference, see <a href="concept-consensus.html">The XRP Ledger Consensus Process</a>.)</p>
|
||||
<p>Whenever <code>rippled</code> closes a ledger, it reorders the transactions according to a deterministic but hard-to-game algorithm. (This is an important part of consensus, since transactions may arrive at different parts of the network in different order.) When using <code>rippled</code> in stand-alone mode, you should manually advance the ledger before submitting a transaction that depends on the result of a transaction from a different address. Otherwise, the two transactions might be executed in reverse order when the ledger is closed. <strong>Note:</strong> You can safely submit multiple transactions from a single address to a single ledger, because <code>rippled</code> sorts transactions from the same address in ascending order by <a href="reference-transaction-format.html#common-fields"><code>Sequence</code> number</a>.</p>
|
||||
<!-- rippled release notes links -->
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<footer class="content-info" role="contentinfo">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-sm-12 absolute_bottom_footer">
|
||||
<div class="col-sm-8">
|
||||
<span>© 2013 - 2017 Ripple Labs, Inc. All Rights Reserved.</span>
|
||||
<span><a href="/terms-of-use/">Terms</a></span>
|
||||
<span><a href="/privacy-policy/">Privacy</a></span>
|
||||
</div>
|
||||
</div><!-- /.absolute_bottom_footer -->
|
||||
|
||||
</div><!-- /.row -->
|
||||
</div><!-- /.container -->
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,363 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<meta name="viewport" content="width=device-width">
|
||||
|
||||
<title>Transaction Cost - Ripple Developer Portal</title>
|
||||
|
||||
<!-- favicon -->
|
||||
<link rel="icon" href="favicon.ico" type="image/x-icon">
|
||||
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon">
|
||||
|
||||
<!-- jQuery -->
|
||||
<script src="assets/vendor/jquery-1.11.1.min.js"></script>
|
||||
|
||||
<!-- Custom Stylesheets. ripple.css includes bootstrap, font stuff -->
|
||||
<link href="assets/css/ripple.css" rel="stylesheet" />
|
||||
<link href="assets/css/devportal.css" rel="stylesheet" />
|
||||
|
||||
<!-- Bootstrap JS -->
|
||||
<script src="assets/vendor/bootstrap.min.js"></script>
|
||||
|
||||
|
||||
<!-- syntax highlighting -->
|
||||
<link rel="stylesheet" href="assets/vendor/docco.min.css" />
|
||||
<script src="assets/vendor/highlight.min.js"></script>
|
||||
|
||||
<!-- syntax selection js -->
|
||||
<script src="assets/js/multicodetab.js"></script>
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
$(".multicode").minitabs();
|
||||
hljs.initHighlighting();
|
||||
make_code_expandable();
|
||||
});
|
||||
</script>
|
||||
|
||||
<script src="assets/js/expandcode.js"></script>
|
||||
<script src="assets/js/fixsidebarscroll.js"></script>
|
||||
|
||||
<!-- fontawesome icons -->
|
||||
<link rel="stylesheet" href="assets/vendor/fontawesome/css/font-awesome.min.css" />
|
||||
|
||||
</head>
|
||||
|
||||
<body class="page page-template page-template-template-dev-portal page-template-template-dev-portal-php sidebar-primary wpb-js-composer js-comp-ver-3.6.2 vc_responsive">
|
||||
<header role="banner" class="banner navbar navbar-default navbar-fixed-top initial_header">
|
||||
<div class="container">
|
||||
<div class="navbar-header">
|
||||
<a href="index.html" class="navbar-brand"><img src="assets/img/ripple-logo-color.png" class="logo"></a>
|
||||
</div><!-- /.navbar-header -->
|
||||
<div class="nav">
|
||||
<div class="draft-warning">DRAFT PAGE</div>
|
||||
</div><!-- /.nav -->
|
||||
|
||||
</div><!-- /.container -->
|
||||
|
||||
<div class="subnav dev_nav">
|
||||
<div class="container">
|
||||
<ul id="menu-dev-menu" class="menu">
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">References <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="reference-rippleapi.html">RippleAPI</a></li>
|
||||
<li><a href="reference-rippled.html">rippled</a></li>
|
||||
<li><a href="reference-transaction-format.html">Transaction Format</a></li>
|
||||
<li><a href="reference-ledger-format.html">Ledger Format</a></li>
|
||||
<li><a href="reference-data-api.html">Ripple Data API v2</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorials <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="tutorial-multisign.html">How to Multi-Sign</a></li>
|
||||
<li><a href="tutorial-paychan.html">Payment Channels Tutorial</a></li>
|
||||
<li><a href="concept-issuing-and-operational-addresses.html">Issuing and Operational Addresses</a></li>
|
||||
<li><a href="tutorial-reliable-transaction-submission.html">Reliable Transaction Submission</a></li>
|
||||
<li><a href="tutorial-rippleapi-beginners-guide.html">RippleAPI Beginners Guide</a></li>
|
||||
<li><a href="tutorial-rippled-setup.html">rippled Setup</a></li>
|
||||
<li><a href="tutorial-gateway-guide.html">Gateway Guide</a></li>
|
||||
<li><a href="tutorial-listing-xrp.html">Listing XRP as an Exchange</a></li>
|
||||
<li><a href="tutorial-escrow.html">Escrow Tutorials</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Features <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="concept-accounts.html">Accounts</a></li>
|
||||
<li><a href="concept-amendments.html">Amendments</a></li>
|
||||
<li><a href="concept-consensus.html">Consensus Process</a></li>
|
||||
<li><a href="concept-reaching-consensus.html">Reaching Consensus in the XRP Ledger</a></li>
|
||||
<li><a href="concept-fee-voting.html">Fee Voting</a></li>
|
||||
<li><a href="concept-fees.html">Fees (Disambiguation)</a></li>
|
||||
<li><a href="concept-freeze.html">Freeze</a></li>
|
||||
<li><a href="concept-partial-payments.html">Partial Payments</a></li>
|
||||
<li><a href="concept-paths.html">Paths</a></li>
|
||||
<li><a href="concept-reserves.html">Reserves</a></li>
|
||||
<li><a href="concept-stand-alone-mode.html">Stand-Alone Mode</a></li>
|
||||
<li><a href="concept-transaction-cost.html">Transaction Cost</a></li>
|
||||
<li><a href="concept-transfer-fees.html">Transfer Fees</a></li>
|
||||
<li><a href="concept-noripple.html">Understanding the NoRipple flag</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Gateway Bulletins <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="gb-2015-06.html">GB-2015-06: Corrections to Autobridging</a></li>
|
||||
<li><a href="gb-2015-05.html">GB-2015-05: Historical Ledger Query Migration</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">API Tools <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="ripple-api-tool.html">WebSocket API Tool</a></li>
|
||||
<li><a href="data-api-v2-tool.html">Data API v2 Tool</a></li>
|
||||
<li><a href="tool-jsonrpc.html">rippled JSON-RPC Tool</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li><a href="https://github.com/ripple/ripple-dev-portal" title="GitHub">Site Source</a></li>
|
||||
</ul><!-- /#dev-menu -->
|
||||
</div><!-- /.subnav .container -->
|
||||
</div><!-- /.subnav -->
|
||||
</header>
|
||||
|
||||
|
||||
<div class="wrap container" role="document">
|
||||
<aside class="sidebar" role="complementary">
|
||||
<div class="dev_nav_wrapper">
|
||||
<div id="cont">
|
||||
<h5>In this category:</h5>
|
||||
<ul class="dev_nav_sidebar">
|
||||
<li class="level-1"><a href="index.html">Category: Features</a></li>
|
||||
<li class="level-2"><a href="concept-accounts.html">Accounts</a></li>
|
||||
<li class="level-2"><a href="concept-amendments.html">Amendments</a></li>
|
||||
<li class="level-2"><a href="concept-consensus.html">Consensus Process</a></li>
|
||||
<li class="level-2"><a href="concept-reaching-consensus.html">Reaching Consensus in the XRP Ledger</a></li>
|
||||
<li class="level-2"><a href="concept-fee-voting.html">Fee Voting</a></li>
|
||||
<li class="level-2"><a href="concept-fees.html">Fees (Disambiguation)</a></li>
|
||||
<li class="level-2"><a href="concept-freeze.html">Freeze</a></li>
|
||||
<li class="level-2"><a href="concept-partial-payments.html">Partial Payments</a></li>
|
||||
<li class="level-2"><a href="concept-paths.html">Paths</a></li>
|
||||
<li class="level-2"><a href="concept-reserves.html">Reserves</a></li>
|
||||
<li class="level-2"><a href="concept-stand-alone-mode.html">Stand-Alone Mode</a></li>
|
||||
<li class="level-2"><a href="concept-transaction-cost.html">Transaction Cost</a></li>
|
||||
<li class="level-2"><a href="concept-transfer-fees.html">Transfer Fees</a></li>
|
||||
<li class="level-2"><a href="concept-noripple.html">Understanding the NoRipple flag</a></li>
|
||||
</ul>
|
||||
<hr />
|
||||
<h5>In this page:</h5>
|
||||
<ul class="dev_nav_sidebar" id="dactyl_toc_sidebar">
|
||||
<li class="level-1"><a href="#transaction-cost">Transaction Cost</a></li>
|
||||
<li class="level-2"><a href="#current-transaction-cost">Current Transaction Cost</a></li>
|
||||
<li class="level-3"><a href="#special-transaction-costs">Special Transaction Costs</a></li>
|
||||
<li class="level-2"><a href="#beneficiaries-of-the-transaction-cost">Beneficiaries of the Transaction Cost</a></li>
|
||||
<li class="level-2"><a href="#load-cost-and-open-ledger-cost">Load Cost and Open Ledger Cost</a></li>
|
||||
<li class="level-2"><a href="#local-load-cost">Local Load Cost</a></li>
|
||||
<li class="level-2"><a href="#open-ledger-cost">Open Ledger Cost</a></li>
|
||||
<li class="level-3"><a href="#queued-transactions">Queued Transactions</a></li>
|
||||
<li class="level-2"><a href="#reference-transaction-cost">Reference Transaction Cost</a></li>
|
||||
<li class="level-3"><a href="#fee-levels">Fee Levels</a></li>
|
||||
<li class="level-2"><a href="#querying-the-transaction-cost">Querying the Transaction Cost</a></li>
|
||||
<li class="level-3"><a href="#server-info">server_info</a></li>
|
||||
<li class="level-3"><a href="#server-state">server_state</a></li>
|
||||
<li class="level-2"><a href="#specifying-the-transaction-cost">Specifying the Transaction Cost</a></li>
|
||||
<li class="level-3"><a href="#automatically-specifying-the-transaction-cost">Automatically Specifying the Transaction Cost</a></li>
|
||||
<li class="level-2"><a href="#transaction-costs-and-failed-transactions">Transaction Costs and Failed Transactions</a></li>
|
||||
<li class="level-3"><a href="#insufficient-xrp">Insufficient XRP</a></li>
|
||||
<li class="level-2"><a href="#key-reset-transaction">Key Reset Transaction</a></li>
|
||||
<li class="level-2"><a href="#changing-the-transaction-cost">Changing the Transaction Cost</a></li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
<main class="main" role="main">
|
||||
<div class='content'>
|
||||
<h1 id="transaction-cost">Transaction Cost</h1>
|
||||
<p>To protect the XRP Ledger from being disrupted by spam and denial-of-service attacks, each transaction must destroy a small amount of <a href="https://ripple.com/xrp-portal/">XRP</a>. This <em>transaction cost</em> is designed to increase along with the load on the network, making it very expensive to deliberately or inadvertently overload the network.</p>
|
||||
<p>Every transaction must <a href="#specifying-the-transaction-cost">specify how much XRP to destroy</a> to pay the transaction cost.</p>
|
||||
<h2 id="current-transaction-cost">Current Transaction Cost</h2>
|
||||
<p>The current minimum transaction cost required by the network for a standard transaction is <strong>0.00001 XRP</strong> (10 drops). It sometimes increases due to higher than usual load.</p>
|
||||
<p>You can also <a href="#querying-the-transaction-cost">query <code>rippled</code> for the current transaction cost</a>.</p>
|
||||
<h3 id="special-transaction-costs">Special Transaction Costs</h3>
|
||||
<p>Some transactions have different transaction costs:</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Transaction</th>
|
||||
<th>Cost Before Load Scaling</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><a href="#reference-transaction-cost">Reference Transaction</a> (Most transactions)</td>
|
||||
<td>10 drops</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="#key-reset-transaction">Key Reset Transaction</a></td>
|
||||
<td>0</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="reference-transaction-format.html#multi-signing">Multi-signed Transaction</a></td>
|
||||
<td>10 drops × (1 + Number of Signatures Provided)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="reference-transaction-format.html#escrowfinish">EscrowFinish Transaction with Fulfillment</a></td>
|
||||
<td>10 drops × (33 + (Fulfillment size in bytes ÷ 16))</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h2 id="beneficiaries-of-the-transaction-cost">Beneficiaries of the Transaction Cost</h2>
|
||||
<p>The transaction cost is not paid to any party: the XRP is irrevocably destroyed. Since no new XRP can ever be created, this makes XRP more scarce and benefits all holders of XRP by making XRP more valuable.</p>
|
||||
<h2 id="load-cost-and-open-ledger-cost">Load Cost and Open Ledger Cost</h2>
|
||||
<p>When the <a href="concept-amendments.html#feeescalation">FeeEscalation amendment</a> is enabled, there are two thresholds for the transaction cost:</p>
|
||||
<ul>
|
||||
<li>If the transaction cost does not meet a <code>rippled</code> server's <a href="#local-load-cost">load-based transaction cost threshold</a>, the server ignores the transaction completely. (This logic is essentially unchanged with or without the amendment.)</li>
|
||||
<li>If the transaction cost does not meet a <code>rippled</code> server's <a href="#open-ledger-cost">open ledger cost threshold</a>, the server queues the transaction for a later ledger.</li>
|
||||
</ul>
|
||||
<p>This divides transactions into roughly three categories:</p>
|
||||
<ul>
|
||||
<li>Transactions that specify a transaction cost so low that they get rejected by the load-based transaction cost.</li>
|
||||
<li>Transactions that specify a transaction cost high enough to be included in the current open ledger.</li>
|
||||
<li>Transactions in between, which get <a href="#queued-transactions">queued for a later ledger version</a>.</li>
|
||||
</ul>
|
||||
<h2 id="local-load-cost">Local Load Cost</h2>
|
||||
<p>Each <code>rippled</code> server maintains a cost threshold based on its current load. If you submit a transaction with a <code>Fee</code> value that is lower than current load-based transaction cost of the <code>rippled</code> server, that server neither applies nor relays the transaction. (<strong>Note:</strong> If you submit a transaction through an <a href="reference-rippled.html#connecting-to-rippled">admin connection</a>, 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 <a href="https://ripple.com/build/ripple-ledger-consensus-process/">the consensus process</a> unless its <code>Fee</code> value meets the requirements of a majority of servers.</p>
|
||||
<h2 id="open-ledger-cost">Open Ledger Cost</h2>
|
||||
<p>The <code>rippled</code> server has a second mechanism for enforcing the transaction cost, called the <em>open ledger cost</em>. 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 <a href="#queued-transactions">queued for a following ledger</a> instead.</p>
|
||||
<p>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.</p>
|
||||
<p>The open ledger cost requirement is <a href="#fee-levels">proportional to the normal cost of the transaction</a>, not the absolute transaction cost. Transaction types that have a higher-than-normal requirement, such as <a href="reference-transaction-format.html#multi-signing">multi-signed transactions</a> must pay more to meet the open ledger cost than transactions which have minimum transaction cost requirements.</p>
|
||||
<p>See also: <a href="https://github.com/ripple/rippled/blob/release/src/ripple/app/misc/FeeEscalation.md">Fee Escalation explanation in <code>rippled</code> repository</a>.</p>
|
||||
<h3 id="queued-transactions">Queued Transactions</h3>
|
||||
<p>When <code>rippled</code> receives a transaction that meet the server's local load cost but not the <a href="#open-ledger-cost">open ledger cost</a>, 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 <a href="#transaction-costs-and-failed-transactions">the transaction cost only applies when a transaction is included in a validated ledger</a>.</p>
|
||||
<p>When the current open ledger closes and the server starts a new open ledger, the server starts taking transactions from the queue to include in the new open ledger. The transaction queue is sorted with the transactions that would pay the highest transaction cost first, proportional to the <a href="#reference-transaction-cost">reference cost</a> of those transactions. Transactions that pay the same transaction cost are queued in the order the server receives them.</p>
|
||||
<p class="devportal-callout note"><strong>Note:</strong> When <code>rippled</code> queues a transaction, the provisional <a href="reference-transaction-format.html#transaction-results">transaction response code</a> is <code>terQUEUED</code>. 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 <a href="reference-transaction-format.html#finality-of-results">rendered permanently invalid</a>.</p>
|
||||
<h4 id="queuing-restrictions">Queuing Restrictions</h4>
|
||||
<p>The <code>rippled</code> 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:</p>
|
||||
<ul>
|
||||
<li>Transactions must be properly-formed and <a href="reference-transaction-format.html#authorizing-transactions">authorized</a> with valid signatures.</li>
|
||||
<li>Transactions with an <code>AccountTxnID</code> field cannot be queued.</li>
|
||||
<li>A single sending address can have at most 10 transactions queued at the same time. In order for a transaction to be queued, the sender must have enough XRP to pay all the XRP costs of all the sender's queued transactions including both the <code>Fee</code> fields and the sum of the XRP that each transaction could send. <a href="https://github.com/ripple/rippled/releases/tag/0.32.0" title="New in: rippled 0.32.0"><img alt="New in: rippled 0.32.0" class="dactyl_badge" src="https://img.shields.io/badge/New%20in-rippled%200.32.0-blue.svg"/></a></li>
|
||||
<li>If a transaction affects how the sending address authorizes transactions, no other transactions from the same address can be queued behind it. <a href="https://github.com/ripple/rippled/releases/tag/0.32.0" title="New in: rippled 0.32.0"><img alt="New in: rippled 0.32.0" class="dactyl_badge" src="https://img.shields.io/badge/New%20in-rippled%200.32.0-blue.svg"/></a></li>
|
||||
<li>If the transaction includes a <code>LastLedgerSequence</code> field, the value of that field must be at least <strong>the current ledger index + 2</strong>.</li>
|
||||
</ul>
|
||||
<h4 id="fee-averaging">Fee Averaging</h4>
|
||||
<p><a href="https://github.com/ripple/rippled/releases/tag/0.33.0" title="New in: rippled 0.33.0"><img alt="New in: rippled 0.33.0" class="dactyl_badge" src="https://img.shields.io/badge/New%20in-rippled%200.33.0-blue.svg"/></a></p>
|
||||
<p>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 increase the total transaction cost of the queued transactions from the same sending address, including the new transaction, to cover the <a href="#open-ledger-cost">open ledger cost</a> of each transaction as it gets added to the ledger. The total must include the increased open ledger cost for each new transaction. The transactions must still follow the other <a href="#queuing-restrictions">queuing restrictions</a> and the sending address must have enough XRP to pay the transaction costs of all the queued transactions.</p>
|
||||
<p>This feature helps you work around a particular situation. If you submitted one or more transactions with a low cost, which got queued, you cannot send new transactions from the same address unless you do one of the following:</p>
|
||||
<ul>
|
||||
<li>Wait for the queued transactions to be included in a validated ledger, <em>or</em></li>
|
||||
<li>Wait for the queued transactions to be permanently invalidated if the transactions have the <a href="tutorial-reliable-transaction-submission.html#lastledgersequence"><code>LastLedgerSequence</code> field</a> set, <em>or</em></li>
|
||||
<li><a href="reference-transaction-format.html#canceling-or-skipping-a-transaction">Cancel the queued transactions</a> by submitting a new transaction with the same sequence number.</li>
|
||||
</ul>
|
||||
<p>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.</p>
|
||||
<h2 id="reference-transaction-cost">Reference Transaction Cost</h2>
|
||||
<p>The "Reference Transaction" is the cheapest (non-free) transaction, in terms of the necessary <a href="concept-transaction-cost.html">transaction cost</a> before load scaling. Most transactions have the same cost as the reference transaction. Some transactions, such as <a href="reference-transaction-format.html#multi-signing">multi-signed transactions</a>, require a multiple of this cost instead. When the open ledger cost escalates, the requirement is proportional to the basic cost of the transaction.</p>
|
||||
<h3 id="fee-levels">Fee Levels</h3>
|
||||
<p><em>Fee levels</em> represent the proportional difference between the minimum cost and the actual cost of a transaction. The <a href="#open-ledger-cost">Open Ledger Cost</a> is measured in fee levels instead of absolute cost. See the following table for a comparison:</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Transaction</th>
|
||||
<th>Minimum cost in drops</th>
|
||||
<th>Minimum cost in Fee levels</th>
|
||||
<th>Double cost in drops</th>
|
||||
<th>Double cost in fee levels</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Reference transaction (most transactions)</td>
|
||||
<td>10</td>
|
||||
<td>256</td>
|
||||
<td>20</td>
|
||||
<td>512</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="reference-transaction-format.html#multi-signing">Multi-signed transaction</a> with 4 signatures</td>
|
||||
<td>50</td>
|
||||
<td>256</td>
|
||||
<td>100</td>
|
||||
<td>512</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="concept-transaction-cost.html#key-reset-transaction">Key reset transaction</a></td>
|
||||
<td>0</td>
|
||||
<td>(Effectively infinite)</td>
|
||||
<td>N/A</td>
|
||||
<td>(Effectively infinite)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="reference-transaction-format.html#escrowfinish">EscrowFinish transaction</a> with 32-byte preimage.</td>
|
||||
<td>350</td>
|
||||
<td>256</td>
|
||||
<td>700</td>
|
||||
<td>512</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h2 id="querying-the-transaction-cost">Querying the Transaction Cost</h2>
|
||||
<p>The <code>rippled</code> APIs have two ways to query the local load-based transaction cost: the <code>server_info</code> command (intended for humans) and the <code>server_state</code> command (intended for machines).</p>
|
||||
<p>If the <a href="concept-amendments.html#feeescalation">FeeEscalation amendment</a> is enabled, you can use the <a href="reference-rippled.html#fee"><code>fee</code> command</a> to check the open ledger cost.</p>
|
||||
<h3 id="server-info">server_info</h3>
|
||||
<p>The <a href="reference-rippled.html#server-info"><code>server_info</code> command</a> reports the unscaled minimum XRP cost, as of the previous ledger, as <code>validated_ledger.base_fee_xrp</code>, in the form of decimal XRP. The actual cost necessary to relay a transaction is scaled by multiplying that <code>base_fee_xrp</code> value by the <code>load_factor</code> parameter in the same response, which represents the server's current load level. In other words:</p>
|
||||
<p><strong>Current Transaction Cost in XRP = <code>base_fee_xrp</code> × <code>load_factor</code></strong></p>
|
||||
<h3 id="server-state">server_state</h3>
|
||||
<p>The <a href="reference-rippled.html#server-state"><code>server_state</code> command</a> returns a direct representation of <code>rippled</code>'s internal load calculations. In this case, the effective load rate is the ratio of the current <code>load_factor</code> to the <code>load_base</code>. The <code>validated_ledger.base_fee</code> parameter reports the minimum transaction cost in <a href="reference-rippled.html#specifying-currency-amounts">drops of XRP</a>. This design enables <code>rippled</code> 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:</p>
|
||||
<p><strong>Current Transaction Cost in Drops = (<code>base_fee</code> × <code>load_factor</code>) ÷ <code>load_base</code></strong></p>
|
||||
<h2 id="specifying-the-transaction-cost">Specifying the Transaction Cost</h2>
|
||||
<p>Every signed transaction must include the transaction cost in the <a href="reference-transaction-format.html#common-fields"><code>Fee</code> field</a>. Like all fields of a signed transaction, this field cannot be changed without invalidating the signature.</p>
|
||||
<p>As a rule, the XRP Ledger executes transactions <em>exactly</em> 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 <code>Fee</code> 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 <a href="concept-reserves.html">reserve requirement</a>.</p>
|
||||
<p>Before signing a transaction, we recommend <a href="#querying-the-transaction-cost">looking up the current load-based transaction cost</a>. 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.</p>
|
||||
<h3 id="automatically-specifying-the-transaction-cost">Automatically Specifying the Transaction Cost</h3>
|
||||
<p>When you sign a transaction online, you can omit the <code>Fee</code> field. In this case, <code>rippled</code> or <a href="reference-rippleapi.html">RippleAPI</a> checks the state of the peer-to-peer network for the current requirement and adds a <code>Fee</code> value before signing the transaction. However, there are several drawbacks and limitations to automatically filling in the transaction cost in this manner:</p>
|
||||
<ul>
|
||||
<li>If the network's transaction cost goes up between signing and distributing the transaction, the transaction may not be confirmed.<ul>
|
||||
<li>In the worst case, the transaction may be stuck in a state of being neither definitively confirmed or rejected, unless it included a <code>LastLedgerSequence</code> parameter or until you cancel it with a new transaction that uses the same <code>Sequence</code> number. See <a href="tutorial-reliable-transaction-submission.html">reliable transaction submission</a> for best practices.</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>You do not know in advance exactly what value you are signing for the <code>Fee</code> field.<ul>
|
||||
<li>If you are using <code>rippled</code>, you can also use the <code>fee_mult_max</code> and <code>fee_div_max</code> parameters of the <a href="reference-rippled.html#sign"><code>sign</code> command</a> to set a limit to the load scaling you are willing to sign.</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>You cannot look up the current transaction cost from an offline machine.</li>
|
||||
<li>You cannot automatically specify the transaction cost when <a href="reference-transaction-format.html#multi-signing">multi-signing</a>.</li>
|
||||
</ul>
|
||||
<h2 id="transaction-costs-and-failed-transactions">Transaction Costs and Failed Transactions</h2>
|
||||
<p>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, <code>rippled</code> servers try to include failed transactions in ledgers, with <a href="reference-transaction-format.html#result-categories"><code>tec</code> status codes</a> ("tec" stands for "Transaction Engine - Claimed fee only").</p>
|
||||
<p>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 <code>tec</code> code.</p>
|
||||
<p>If a transaction's failure is <a href="reference-transaction-format.html#finality-of-results">final</a>, the <code>rippled</code> 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.</p>
|
||||
<h3 id="insufficient-xrp">Insufficient XRP</h3>
|
||||
<p>When a <code>rippled</code> server initially evaluates a transaction, it rejects the transaction with the error code <code>terINSUF_FEE_B</code> if the sending account does not have a high enough XRP balance to pay the XRP transaction cost. Since this is a <code>ter</code> (Retry) code, the <code>rippled</code> server retries the transaction without relaying it to the network, until the transaction's outcome is <a href="reference-transaction-format.html#finality-of-results">final</a>.</p>
|
||||
<p>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 <code>tecINSUFF_FEE</code> occurs instead. In this case, the account pays all the XRP it can, ending with 0 XRP. This can occur because <code>rippled</code> 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.</p>
|
||||
<h2 id="key-reset-transaction">Key Reset Transaction</h2>
|
||||
<p>As a special case, an account can send a <a href="reference-transaction-format.html#setregularkey">SetRegularKey</a> transaction with a transaction cost of <code>0</code>, as long as the account's <a href="reference-ledger-format.html#accountroot-flags">lsfPasswordSpent flag</a> is disabled. This transaction must be signed by the account's <em>master key pair</em>. Sending this transaction enables the lsfPasswordSpent flag.</p>
|
||||
<p>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.</p>
|
||||
<p>The <a href="reference-ledger-format.html#accountroot-flags">lsfPasswordSpent flag</a> 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 <a href="reference-transaction-format.html#payment">Payment</a> of XRP.</p>
|
||||
<p>When the <a href="concept-amendments.html#feeescalation">FeeEscalation amendment</a> is enabled, <code>rippled</code> prioritizes key reset transactions above other transactions even though the nominal transaction cost of a key reset transaction is zero.</p>
|
||||
<h2 id="changing-the-transaction-cost">Changing the Transaction Cost</h2>
|
||||
<p>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 <a href="concept-fee-voting.html">Fee Voting</a> for more information.</p>
|
||||
<!-- rippled release notes links -->
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<footer class="content-info" role="contentinfo">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-sm-12 absolute_bottom_footer">
|
||||
<div class="col-sm-8">
|
||||
<span>© 2013 - 2017 Ripple Labs, Inc. All Rights Reserved.</span>
|
||||
<span><a href="/terms-of-use/">Terms</a></span>
|
||||
<span><a href="/privacy-policy/">Privacy</a></span>
|
||||
</div>
|
||||
</div><!-- /.absolute_bottom_footer -->
|
||||
|
||||
</div><!-- /.row -->
|
||||
</div><!-- /.container -->
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,210 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<meta name="viewport" content="width=device-width">
|
||||
|
||||
<title>Transfer Fees - Ripple Developer Portal</title>
|
||||
|
||||
<!-- favicon -->
|
||||
<link rel="icon" href="favicon.ico" type="image/x-icon">
|
||||
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon">
|
||||
|
||||
<!-- jQuery -->
|
||||
<script src="assets/vendor/jquery-1.11.1.min.js"></script>
|
||||
|
||||
<!-- Custom Stylesheets. ripple.css includes bootstrap, font stuff -->
|
||||
<link href="assets/css/ripple.css" rel="stylesheet" />
|
||||
<link href="assets/css/devportal.css" rel="stylesheet" />
|
||||
|
||||
<!-- Bootstrap JS -->
|
||||
<script src="assets/vendor/bootstrap.min.js"></script>
|
||||
|
||||
|
||||
<!-- syntax highlighting -->
|
||||
<link rel="stylesheet" href="assets/vendor/docco.min.css" />
|
||||
<script src="assets/vendor/highlight.min.js"></script>
|
||||
|
||||
<!-- syntax selection js -->
|
||||
<script src="assets/js/multicodetab.js"></script>
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
$(".multicode").minitabs();
|
||||
hljs.initHighlighting();
|
||||
make_code_expandable();
|
||||
});
|
||||
</script>
|
||||
|
||||
<script src="assets/js/expandcode.js"></script>
|
||||
<script src="assets/js/fixsidebarscroll.js"></script>
|
||||
|
||||
<!-- fontawesome icons -->
|
||||
<link rel="stylesheet" href="assets/vendor/fontawesome/css/font-awesome.min.css" />
|
||||
|
||||
</head>
|
||||
|
||||
<body class="page page-template page-template-template-dev-portal page-template-template-dev-portal-php sidebar-primary wpb-js-composer js-comp-ver-3.6.2 vc_responsive">
|
||||
<header role="banner" class="banner navbar navbar-default navbar-fixed-top initial_header">
|
||||
<div class="container">
|
||||
<div class="navbar-header">
|
||||
<a href="index.html" class="navbar-brand"><img src="assets/img/ripple-logo-color.png" class="logo"></a>
|
||||
</div><!-- /.navbar-header -->
|
||||
<div class="nav">
|
||||
<div class="draft-warning">DRAFT PAGE</div>
|
||||
</div><!-- /.nav -->
|
||||
|
||||
</div><!-- /.container -->
|
||||
|
||||
<div class="subnav dev_nav">
|
||||
<div class="container">
|
||||
<ul id="menu-dev-menu" class="menu">
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">References <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="reference-rippleapi.html">RippleAPI</a></li>
|
||||
<li><a href="reference-rippled.html">rippled</a></li>
|
||||
<li><a href="reference-transaction-format.html">Transaction Format</a></li>
|
||||
<li><a href="reference-ledger-format.html">Ledger Format</a></li>
|
||||
<li><a href="reference-data-api.html">Ripple Data API v2</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorials <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="tutorial-multisign.html">How to Multi-Sign</a></li>
|
||||
<li><a href="tutorial-paychan.html">Payment Channels Tutorial</a></li>
|
||||
<li><a href="concept-issuing-and-operational-addresses.html">Issuing and Operational Addresses</a></li>
|
||||
<li><a href="tutorial-reliable-transaction-submission.html">Reliable Transaction Submission</a></li>
|
||||
<li><a href="tutorial-rippleapi-beginners-guide.html">RippleAPI Beginners Guide</a></li>
|
||||
<li><a href="tutorial-rippled-setup.html">rippled Setup</a></li>
|
||||
<li><a href="tutorial-gateway-guide.html">Gateway Guide</a></li>
|
||||
<li><a href="tutorial-listing-xrp.html">Listing XRP as an Exchange</a></li>
|
||||
<li><a href="tutorial-escrow.html">Escrow Tutorials</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Features <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="concept-accounts.html">Accounts</a></li>
|
||||
<li><a href="concept-amendments.html">Amendments</a></li>
|
||||
<li><a href="concept-consensus.html">Consensus Process</a></li>
|
||||
<li><a href="concept-reaching-consensus.html">Reaching Consensus in the XRP Ledger</a></li>
|
||||
<li><a href="concept-fee-voting.html">Fee Voting</a></li>
|
||||
<li><a href="concept-fees.html">Fees (Disambiguation)</a></li>
|
||||
<li><a href="concept-freeze.html">Freeze</a></li>
|
||||
<li><a href="concept-partial-payments.html">Partial Payments</a></li>
|
||||
<li><a href="concept-paths.html">Paths</a></li>
|
||||
<li><a href="concept-reserves.html">Reserves</a></li>
|
||||
<li><a href="concept-stand-alone-mode.html">Stand-Alone Mode</a></li>
|
||||
<li><a href="concept-transaction-cost.html">Transaction Cost</a></li>
|
||||
<li><a href="concept-transfer-fees.html">Transfer Fees</a></li>
|
||||
<li><a href="concept-noripple.html">Understanding the NoRipple flag</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Gateway Bulletins <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="gb-2015-06.html">GB-2015-06: Corrections to Autobridging</a></li>
|
||||
<li><a href="gb-2015-05.html">GB-2015-05: Historical Ledger Query Migration</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">API Tools <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="ripple-api-tool.html">WebSocket API Tool</a></li>
|
||||
<li><a href="data-api-v2-tool.html">Data API v2 Tool</a></li>
|
||||
<li><a href="tool-jsonrpc.html">rippled JSON-RPC Tool</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li><a href="https://github.com/ripple/ripple-dev-portal" title="GitHub">Site Source</a></li>
|
||||
</ul><!-- /#dev-menu -->
|
||||
</div><!-- /.subnav .container -->
|
||||
</div><!-- /.subnav -->
|
||||
</header>
|
||||
|
||||
|
||||
<div class="wrap container" role="document">
|
||||
<aside class="sidebar" role="complementary">
|
||||
<div class="dev_nav_wrapper">
|
||||
<div id="cont">
|
||||
<h5>In this category:</h5>
|
||||
<ul class="dev_nav_sidebar">
|
||||
<li class="level-1"><a href="index.html">Category: Features</a></li>
|
||||
<li class="level-2"><a href="concept-accounts.html">Accounts</a></li>
|
||||
<li class="level-2"><a href="concept-amendments.html">Amendments</a></li>
|
||||
<li class="level-2"><a href="concept-consensus.html">Consensus Process</a></li>
|
||||
<li class="level-2"><a href="concept-reaching-consensus.html">Reaching Consensus in the XRP Ledger</a></li>
|
||||
<li class="level-2"><a href="concept-fee-voting.html">Fee Voting</a></li>
|
||||
<li class="level-2"><a href="concept-fees.html">Fees (Disambiguation)</a></li>
|
||||
<li class="level-2"><a href="concept-freeze.html">Freeze</a></li>
|
||||
<li class="level-2"><a href="concept-partial-payments.html">Partial Payments</a></li>
|
||||
<li class="level-2"><a href="concept-paths.html">Paths</a></li>
|
||||
<li class="level-2"><a href="concept-reserves.html">Reserves</a></li>
|
||||
<li class="level-2"><a href="concept-stand-alone-mode.html">Stand-Alone Mode</a></li>
|
||||
<li class="level-2"><a href="concept-transaction-cost.html">Transaction Cost</a></li>
|
||||
<li class="level-2"><a href="concept-transfer-fees.html">Transfer Fees</a></li>
|
||||
<li class="level-2"><a href="concept-noripple.html">Understanding the NoRipple flag</a></li>
|
||||
</ul>
|
||||
<hr />
|
||||
<h5>In this page:</h5>
|
||||
<ul class="dev_nav_sidebar" id="dactyl_toc_sidebar">
|
||||
<li class="level-1"><a href="#transfer-fees">Transfer Fees</a></li>
|
||||
<li class="level-2"><a href="#transfer-fees-in-payment-paths">Transfer Fees in Payment Paths</a></li>
|
||||
<li class="level-1"><a href="#technical-details">Technical Details</a></li>
|
||||
<li class="level-2"><a href="#rippleapi">RippleAPI</a></li>
|
||||
<li class="level-2"><a href="#rippled">rippled</a></li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
<main class="main" role="main">
|
||||
<div class='content'>
|
||||
<h1 id="transfer-fees">Transfer Fees</h1>
|
||||
<p>The <code>TransferRate</code> setting in the XRP Ledger allows <a href="tutorial-gateway-guide.html">financial institutions that issue currency in the XRP Ledger</a> to charge users a <em>transfer fee</em> for sending the currencies issued by that financial institution. The sender of the transfer is debited an extra percentage based on the transfer fee, while the recipient of the transfer is credited the intended amount. The difference is the transfer fee, which becomes the property of the issuing address, and is no longer tracked in the XRP Ledger. The transfer fee does not apply when sending or receiving <em>directly</em> to and from the issuing account, but it does apply when transferring from an <a href="concept-issuing-and-operational-addresses.html">operational address</a> to another user.</p>
|
||||
<p>XRP never has a transfer fee, because it never has an issuer.</p>
|
||||
<p>For example, ACME Bank might set the transfer fee to 0.5% for ACME issuances. For the recipient of a payment to get 2 EUR.ACME, the sender must send 2.01 EUR.ACME. After the transaction, ACME's outstanding obligations in the XRP Ledger have decreased by 0.01€, which means that ACME no longer needs to hold that amount in the account backing its XRP Ledger issuances.</p>
|
||||
<p>The following diagram shows an XRP Ledger payment of 2 EUR.ACME from Alice to Charlie with a transfer fee of 1%:</p>
|
||||
<p><img alt="Alice sends 2,02€, Charlie receives 2,00€, and ACME owes 0,02€ less in the XRP Ledger" src="img/e2g-with_transferrate.png"/></p>
|
||||
<h2 id="transfer-fees-in-payment-paths">Transfer Fees in Payment Paths</h2>
|
||||
<!-- -->
|
||||
<p>A transfer fee applies whenever an individual transfer would shift issuances from one party to another through the issuing account. In more complex transactions, this can occur multiple times. Transfer fees apply starting from the end and working backwards, so that ultimately the sender of a payment must send enough to account for all fees. For example:</p>
|
||||
<p><img alt="Diagram of cross-currency payment with transfer fees" src="img/transfer_fees_example.png"/></p>
|
||||
<p>In this scenario, Salazar (the sender) holds EUR issued by ACME, and wants to deliver 100 USD issued by WayGate to Rosa (the recipient). FXMaker is a currency trader with the best offer in the order book, at a rate of 1 USD.WayGate for every 0.9 EUR.ACME. If there were no transfer fees, Salazar could deliver 100 USD to Rosa by sending 90 EUR. However, ACME has a transfer fee of 1% and WayGate has a transfer fee of 0.2%. This means:</p>
|
||||
<ul>
|
||||
<li>FXMaker must send 100.20 USD.WayGate for Rosa to receive 100 USD.WayGate.</li>
|
||||
<li>FXMaker's current ask is 90.18 EUR.ACME to send 100.20 USD.WayGate.</li>
|
||||
<li>For FXMaker to receive 90.18 EUR.ACME, Salazar must send 91.0818 EUR.ACME.</li>
|
||||
</ul>
|
||||
<h1 id="technical-details">Technical Details</h1>
|
||||
<p>The transfer fee is represented by a setting on the <a href="concept-issuing-and-operational-addresses.html">issuing address</a>. The transfer fee has a maximum precision of 9 digits, and cannot be less than 0%. The TransferRate setting applies to all currencies issued by the same account. If you want to have different transfer fee percentages for different currencies, use different <a href="concept-issuing-and-operational-addresses.html">issuing addresses</a> for each currency.</p>
|
||||
<h2 id="rippleapi">RippleAPI</h2>
|
||||
<p>In RippleAPI, the transfer fee is specified in the <code>transferRate</code> field, as a decimal which represents the amount you must send for the recipient to get 1 unit of the same currency. A <code>transferRate</code> of <code>1.005</code> is equivalent to a transfer fee of 0.5%. By default, the <code>transferRate</code> is set to no fee. The value of <code>transferRate</code> cannot be less than <code>1.0</code> or more than <code>4.294967295</code>. The value <code>null</code> is a special case for no fee, equivalent to <code>1000000000</code>.</p>
|
||||
<p>A financial institution can send a <a href="reference-rippleapi.html#settings">Settings transaction</a> from its <a href="concept-issuing-and-operational-addresses.html">issuing address</a> to change the <code>transferRate</code> for its issuances.</p>
|
||||
<p>You can check an account's <code>transferRate</code> with the <a href="reference-rippleapi.html#getsettings">getSettings method</a>.</p>
|
||||
<h2 id="rippled">rippled</h2>
|
||||
<p>In <code>rippled</code>'s JSON-RPC and WebSocket APIs, the transfer fee is specified in the <code>TransferRate</code> field, as an integer which represents the amount you must send for the recipient to get 1 billion units of the same currency. A <code>TransferRate</code> of <code>1005000000</code> is equivalent to a transfer fee of 0.5%. By default, the <code>TransferRate</code> is set to no fee. The value of <code>TransferRate</code> cannot be less than <code>1000000000</code> or more than <code>4294967295</code> (the maximum value of a 32-bit unsigned integer). The value <code>0</code> is special case for no fee, equivalent to <code>1000000000</code>.</p>
|
||||
<p>A financial institution can submit an <a href="reference-transaction-format.html#accountset">AccountSet transaction</a> from its <a href="concept-issuing-and-operational-addresses.html">issuing address</a> to change the <code>TransferRate</code> for its issuances.</p>
|
||||
<p>You can check an account's <code>TransferRate</code> with the <a href="reference-rippled.html#account-info"><code>account_info</code> command</a>. If the <code>TransferRate</code> is omitted, then that indicates no fee.</p>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<footer class="content-info" role="contentinfo">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-sm-12 absolute_bottom_footer">
|
||||
<div class="col-sm-8">
|
||||
<span>© 2013 - 2017 Ripple Labs, Inc. All Rights Reserved.</span>
|
||||
<span><a href="/terms-of-use/">Terms</a></span>
|
||||
<span><a href="/privacy-policy/">Privacy</a></span>
|
||||
</div>
|
||||
</div><!-- /.absolute_bottom_footer -->
|
||||
|
||||
</div><!-- /.row -->
|
||||
</div><!-- /.container -->
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,27 +1,25 @@
|
||||
# Relative paths work OK as long as you start the tool from its local dir
|
||||
template_path: .
|
||||
template_path: tool
|
||||
|
||||
# This folder gets copied into the output directory
|
||||
template_static_path: ../assets
|
||||
template_static_path: assets
|
||||
|
||||
# Templates should have filenames starting in template-
|
||||
default_template: template-doc.html
|
||||
pdf_template: template-forpdf.html
|
||||
default_pdf_template: template-forpdf.html
|
||||
|
||||
# HTML, PDF, GFM all get output here
|
||||
out_path: ..
|
||||
out_path: out
|
||||
|
||||
# MD files should be here (and in subdirs)
|
||||
content_path: ../content
|
||||
content_path: content
|
||||
|
||||
# This folder gets copied into the output directory
|
||||
content_static_path: ../img
|
||||
content_static_path: img
|
||||
|
||||
# PDF creation needs a dir for temporary files
|
||||
temporary_files_path: /tmp/
|
||||
|
||||
prince_executable: prince
|
||||
|
||||
default_filters:
|
||||
- multicode_tabs
|
||||
- standardize_header_ids
|
||||
@@ -1,184 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<meta name="viewport" content="width=device-width">
|
||||
|
||||
<title>Data API v2 Tool - Ripple Developer Portal</title>
|
||||
|
||||
<!-- favicon -->
|
||||
<link rel="icon" href="favicon.ico" type="image/x-icon">
|
||||
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon">
|
||||
|
||||
<!-- jQuery -->
|
||||
<script src="assets/vendor/jquery-1.11.1.min.js"></script>
|
||||
|
||||
<!-- Custom Stylesheets. ripple.css includes bootstrap, font stuff -->
|
||||
<link href="assets/css/ripple.css" rel="stylesheet" />
|
||||
<link href="assets/css/devportal.css" rel="stylesheet" />
|
||||
|
||||
<!-- Bootstrap JS -->
|
||||
<script src="assets/vendor/bootstrap.min.js"></script>
|
||||
|
||||
|
||||
|
||||
</head>
|
||||
|
||||
<body class="page page-template page-template-template-dev-portal page-template-template-dev-portal-php sidebar-primary wpb-js-composer js-comp-ver-3.6.2 vc_responsive">
|
||||
<header role="banner" class="banner navbar navbar-default navbar-fixed-top initial_header">
|
||||
<div class="container">
|
||||
<div class="navbar-header">
|
||||
<a href="index.html" class="navbar-brand"><img src="assets/img/ripple-logo-color.png" class="logo"></a>
|
||||
</div><!-- /.navbar-header -->
|
||||
<div class="nav">
|
||||
<div class="draft-warning">DRAFT PAGE</div>
|
||||
</div><!-- /.nav -->
|
||||
|
||||
</div><!-- /.container -->
|
||||
|
||||
<div class="subnav dev_nav">
|
||||
<div class="container">
|
||||
<ul id="menu-dev-menu" class="menu">
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">References <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="reference-rippleapi.html">RippleAPI</a></li>
|
||||
<li><a href="reference-rippled.html">rippled</a></li>
|
||||
<li><a href="reference-transaction-format.html">Transaction Format</a></li>
|
||||
<li><a href="reference-ledger-format.html">Ledger Format</a></li>
|
||||
<li><a href="reference-data-api.html">Ripple Data API v2</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorials <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="tutorial-multisign.html">How to Multi-Sign</a></li>
|
||||
<li><a href="tutorial-paychan.html">Payment Channels Tutorial</a></li>
|
||||
<li><a href="concept-issuing-and-operational-addresses.html">Issuing and Operational Addresses</a></li>
|
||||
<li><a href="tutorial-reliable-transaction-submission.html">Reliable Transaction Submission</a></li>
|
||||
<li><a href="tutorial-rippleapi-beginners-guide.html">RippleAPI Beginners Guide</a></li>
|
||||
<li><a href="tutorial-rippled-setup.html">rippled Setup</a></li>
|
||||
<li><a href="tutorial-gateway-guide.html">Gateway Guide</a></li>
|
||||
<li><a href="tutorial-listing-xrp.html">Listing XRP as an Exchange</a></li>
|
||||
<li><a href="tutorial-escrow.html">Escrow Tutorials</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Features <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="concept-accounts.html">Accounts</a></li>
|
||||
<li><a href="concept-amendments.html">Amendments</a></li>
|
||||
<li><a href="concept-consensus.html">Consensus Process</a></li>
|
||||
<li><a href="concept-reaching-consensus.html">Reaching Consensus in the XRP Ledger</a></li>
|
||||
<li><a href="concept-fee-voting.html">Fee Voting</a></li>
|
||||
<li><a href="concept-fees.html">Fees (Disambiguation)</a></li>
|
||||
<li><a href="concept-freeze.html">Freeze</a></li>
|
||||
<li><a href="concept-partial-payments.html">Partial Payments</a></li>
|
||||
<li><a href="concept-paths.html">Paths</a></li>
|
||||
<li><a href="concept-reserves.html">Reserves</a></li>
|
||||
<li><a href="concept-stand-alone-mode.html">Stand-Alone Mode</a></li>
|
||||
<li><a href="concept-transaction-cost.html">Transaction Cost</a></li>
|
||||
<li><a href="concept-transfer-fees.html">Transfer Fees</a></li>
|
||||
<li><a href="concept-noripple.html">Understanding the NoRipple flag</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Gateway Bulletins <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="gb-2015-06.html">GB-2015-06: Corrections to Autobridging</a></li>
|
||||
<li><a href="gb-2015-05.html">GB-2015-05: Historical Ledger Query Migration</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">API Tools <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="ripple-api-tool.html">WebSocket API Tool</a></li>
|
||||
<li><a href="data-api-v2-tool.html">Data API v2 Tool</a></li>
|
||||
<li><a href="tool-jsonrpc.html">rippled JSON-RPC Tool</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li><a href="https://github.com/ripple/ripple-dev-portal" title="GitHub">Site Source</a></li>
|
||||
</ul><!-- /#dev-menu -->
|
||||
</div><!-- /.subnav .container -->
|
||||
</div><!-- /.subnav -->
|
||||
</header>
|
||||
|
||||
|
||||
<div class="wrap container" role="document">
|
||||
<aside class="sidebar" role="complementary">
|
||||
<ul id='command_list'>
|
||||
</ul>
|
||||
</aside>
|
||||
<main class="main" role="main">
|
||||
<div id='wrapper'>
|
||||
<div style="clear:both;"></div>
|
||||
<div id='command_wrapper'>
|
||||
<div id='command_table'>
|
||||
<div id='io_wrapper'>
|
||||
<div id='input' class='io'>
|
||||
<h2>REST Request</h2>
|
||||
<div id='test_warning' class='alert alert-danger' style='display:none;'>
|
||||
<h4>Test accounts only!</h4>
|
||||
<p>Never submit account secrets to a server you do not control, unless you are prepared to lose ownership of the account!</p>
|
||||
</div>
|
||||
<div style="clear:both;"></div>
|
||||
<h3 id='selected_command' title='Reference information'></h3>
|
||||
<p id='description'></p>
|
||||
<div id='invalid'>Invalid JSON</div>
|
||||
<div id='rest_url_wrapper'>
|
||||
<p><span id='rest_host'>https://data.ripple.com</span><span id='rest_url'></span></p>
|
||||
</div>
|
||||
<div id='request_body'></div>
|
||||
<div id='request_options'>
|
||||
<a class="button btn btn-primary api" id='request_button'>Send request</a>
|
||||
</div>
|
||||
</div>
|
||||
<div id='output' class='io'>
|
||||
<h2>Response</h2>
|
||||
<div>
|
||||
<img class="loader" src="assets/img/rippleThrobber.png" style="vertical-align: middle; display:none;"/>
|
||||
<span id='rest_responsecode'></span>
|
||||
</div>
|
||||
<div id='response_body'></div>
|
||||
<div id='tooltip'></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script type='text/javascript'>
|
||||
// Set some constants for the REST tool script
|
||||
var URL_BASE = 'https://data.ripple.com';
|
||||
var DOC_BASE = 'reference-data-api.html';
|
||||
</script>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<footer class="content-info" role="contentinfo">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-sm-12 absolute_bottom_footer">
|
||||
<div class="col-sm-8">
|
||||
<span>© 2013 - 2017 Ripple Labs, Inc. All Rights Reserved.</span>
|
||||
<span><a href="/terms-of-use/">Terms</a></span>
|
||||
<span><a href="/privacy-policy/">Privacy</a></span>
|
||||
</div>
|
||||
</div><!-- /.absolute_bottom_footer -->
|
||||
|
||||
</div><!-- /.row -->
|
||||
</div><!-- /.container -->
|
||||
</footer>
|
||||
|
||||
<link rel='stylesheet' type='text/css' href='assets/css/api-tools.css'/>
|
||||
<link rel='stylesheet' type='text/css' href='assets/vendor/codemirror.css'/>
|
||||
<script type='text/javascript' src='assets/js/es5-shim.js'></script>
|
||||
<script type='text/javascript' src='assets/vendor/codemirror.min.js'></script>
|
||||
<script type='text/javascript' src='assets/vendor/cm-javascript.min.js'></script>
|
||||
<script type='text/javascript' src='assets/js/jquery.autosize.input.min.js'></script>
|
||||
<script type='text/javascript' src='assets/js/apitool-rest.js'></script>
|
||||
<script type='text/javascript' src='assets/js/apitool-methods-data_v2.js'></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
197
gb-2015-05.html
197
gb-2015-05.html
@@ -1,197 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<meta name="viewport" content="width=device-width">
|
||||
|
||||
<title>GB-2015-05: Historical Ledger Query Migration - Ripple Developer Portal</title>
|
||||
|
||||
<!-- favicon -->
|
||||
<link rel="icon" href="favicon.ico" type="image/x-icon">
|
||||
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon">
|
||||
|
||||
<!-- jQuery -->
|
||||
<script src="assets/vendor/jquery-1.11.1.min.js"></script>
|
||||
|
||||
<!-- Custom Stylesheets. ripple.css includes bootstrap, font stuff -->
|
||||
<link href="assets/css/ripple.css" rel="stylesheet" />
|
||||
<link href="assets/css/devportal.css" rel="stylesheet" />
|
||||
|
||||
<!-- Bootstrap JS -->
|
||||
<script src="assets/vendor/bootstrap.min.js"></script>
|
||||
|
||||
|
||||
<!-- syntax highlighting -->
|
||||
<link rel="stylesheet" href="assets/vendor/docco.min.css" />
|
||||
<script src="assets/vendor/highlight.min.js"></script>
|
||||
|
||||
<!-- syntax selection js -->
|
||||
<script src="assets/js/multicodetab.js"></script>
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
$(".multicode").minitabs();
|
||||
hljs.initHighlighting();
|
||||
make_code_expandable();
|
||||
});
|
||||
</script>
|
||||
|
||||
<script src="assets/js/expandcode.js"></script>
|
||||
<script src="assets/js/fixsidebarscroll.js"></script>
|
||||
|
||||
<!-- fontawesome icons -->
|
||||
<link rel="stylesheet" href="assets/vendor/fontawesome/css/font-awesome.min.css" />
|
||||
|
||||
</head>
|
||||
|
||||
<body class="page page-template page-template-template-dev-portal page-template-template-dev-portal-php sidebar-primary wpb-js-composer js-comp-ver-3.6.2 vc_responsive">
|
||||
<header role="banner" class="banner navbar navbar-default navbar-fixed-top initial_header">
|
||||
<div class="container">
|
||||
<div class="navbar-header">
|
||||
<a href="index.html" class="navbar-brand"><img src="assets/img/ripple-logo-color.png" class="logo"></a>
|
||||
</div><!-- /.navbar-header -->
|
||||
<div class="nav">
|
||||
<div class="draft-warning">DRAFT PAGE</div>
|
||||
</div><!-- /.nav -->
|
||||
|
||||
</div><!-- /.container -->
|
||||
|
||||
<div class="subnav dev_nav">
|
||||
<div class="container">
|
||||
<ul id="menu-dev-menu" class="menu">
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">References <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="reference-rippleapi.html">RippleAPI</a></li>
|
||||
<li><a href="reference-rippled.html">rippled</a></li>
|
||||
<li><a href="reference-transaction-format.html">Transaction Format</a></li>
|
||||
<li><a href="reference-ledger-format.html">Ledger Format</a></li>
|
||||
<li><a href="reference-data-api.html">Ripple Data API v2</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorials <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="tutorial-multisign.html">How to Multi-Sign</a></li>
|
||||
<li><a href="tutorial-paychan.html">Payment Channels Tutorial</a></li>
|
||||
<li><a href="concept-issuing-and-operational-addresses.html">Issuing and Operational Addresses</a></li>
|
||||
<li><a href="tutorial-reliable-transaction-submission.html">Reliable Transaction Submission</a></li>
|
||||
<li><a href="tutorial-rippleapi-beginners-guide.html">RippleAPI Beginners Guide</a></li>
|
||||
<li><a href="tutorial-rippled-setup.html">rippled Setup</a></li>
|
||||
<li><a href="tutorial-gateway-guide.html">Gateway Guide</a></li>
|
||||
<li><a href="tutorial-listing-xrp.html">Listing XRP as an Exchange</a></li>
|
||||
<li><a href="tutorial-escrow.html">Escrow Tutorials</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Features <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="concept-accounts.html">Accounts</a></li>
|
||||
<li><a href="concept-amendments.html">Amendments</a></li>
|
||||
<li><a href="concept-consensus.html">Consensus Process</a></li>
|
||||
<li><a href="concept-reaching-consensus.html">Reaching Consensus in the XRP Ledger</a></li>
|
||||
<li><a href="concept-fee-voting.html">Fee Voting</a></li>
|
||||
<li><a href="concept-fees.html">Fees (Disambiguation)</a></li>
|
||||
<li><a href="concept-freeze.html">Freeze</a></li>
|
||||
<li><a href="concept-partial-payments.html">Partial Payments</a></li>
|
||||
<li><a href="concept-paths.html">Paths</a></li>
|
||||
<li><a href="concept-reserves.html">Reserves</a></li>
|
||||
<li><a href="concept-stand-alone-mode.html">Stand-Alone Mode</a></li>
|
||||
<li><a href="concept-transaction-cost.html">Transaction Cost</a></li>
|
||||
<li><a href="concept-transfer-fees.html">Transfer Fees</a></li>
|
||||
<li><a href="concept-noripple.html">Understanding the NoRipple flag</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Gateway Bulletins <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="gb-2015-06.html">GB-2015-06: Corrections to Autobridging</a></li>
|
||||
<li><a href="gb-2015-05.html">GB-2015-05: Historical Ledger Query Migration</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">API Tools <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="ripple-api-tool.html">WebSocket API Tool</a></li>
|
||||
<li><a href="data-api-v2-tool.html">Data API v2 Tool</a></li>
|
||||
<li><a href="tool-jsonrpc.html">rippled JSON-RPC Tool</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li><a href="https://github.com/ripple/ripple-dev-portal" title="GitHub">Site Source</a></li>
|
||||
</ul><!-- /#dev-menu -->
|
||||
</div><!-- /.subnav .container -->
|
||||
</div><!-- /.subnav -->
|
||||
</header>
|
||||
|
||||
|
||||
<div class="wrap container" role="document">
|
||||
<aside class="sidebar" role="complementary">
|
||||
<div class="dev_nav_wrapper">
|
||||
<div id="cont">
|
||||
<h5>In this category:</h5>
|
||||
<ul class="dev_nav_sidebar">
|
||||
<li class="level-1"><a href="index.html">Category: Gateway Bulletins</a></li>
|
||||
<li class="level-2"><a href="gb-2015-06.html">GB-2015-06: Corrections to Autobridging</a></li>
|
||||
<li class="level-2"><a href="gb-2015-05.html">GB-2015-05: Historical Ledger Query Migration</a></li>
|
||||
</ul>
|
||||
<hr />
|
||||
<h5>In this page:</h5>
|
||||
<ul class="dev_nav_sidebar" id="dactyl_toc_sidebar">
|
||||
<li class="level-1"><a href="#gb-2015-05-historical-ledger-query-migration">GB-2015-05: Historical Ledger Query Migration</a></li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
<main class="main" role="main">
|
||||
<div class='content'>
|
||||
<h1 id="gb-2015-05-historical-ledger-query-migration">GB-2015-05: Historical Ledger Query Migration</h1>
|
||||
<p>In the past, Ripple Labs has supplied the rippled cluster,
|
||||
s1.ripple.com, with full historical ledgers and transactions for public
|
||||
access. Moving forward, we would like to inform our partners and
|
||||
community to migrate to the Historical Database. Instructions for
|
||||
migration are linked below. <strong>s1.ripple.com will no longer store full
|
||||
history and provide the ability to query for historical ledgers and
|
||||
transactions.</strong> In order to continue providing interested parties with
|
||||
historical data, Ripple Labs will be offering a REST based service that
|
||||
will provide the ability to query against all historical transactions
|
||||
based upon a specific Ripple address. This however will not address the
|
||||
ability to retrieve historical ledger states or historical order books.
|
||||
<strong>Action Required For Historical Ledger Queries</strong> Starting on <strong>May 1,
|
||||
2015</strong>, the public rippled cluster s1.ripple.com will store 1 month of
|
||||
ledger history. Please consider one of the options below if historical
|
||||
data is needed:</p>
|
||||
<ul>
|
||||
<li>To access historical <strong>transactions</strong> per account (<code>account_tx</code> and <code>tx</code> calls) :<ul>
|
||||
<li>Use the Ripple Historical Database service (<a href="https://ripple.com/build/data-api-v2/">https://ripple.com/build/data-api-v2/</a>)</li>
|
||||
<li>Configure and start your own full history rippled server</li>
|
||||
<li>Use s2.ripple.com public cluster</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>To access historical <strong>ledgers</strong> and <strong>order books</strong><ul>
|
||||
<li>Configure and start your own full history rippled server</li>
|
||||
<li>Use s2.ripple.com public cluster.</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<footer class="content-info" role="contentinfo">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-sm-12 absolute_bottom_footer">
|
||||
<div class="col-sm-8">
|
||||
<span>© 2013 - 2017 Ripple Labs, Inc. All Rights Reserved.</span>
|
||||
<span><a href="/terms-of-use/">Terms</a></span>
|
||||
<span><a href="/privacy-policy/">Privacy</a></span>
|
||||
</div>
|
||||
</div><!-- /.absolute_bottom_footer -->
|
||||
|
||||
</div><!-- /.row -->
|
||||
</div><!-- /.container -->
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
182
gb-2015-06.html
182
gb-2015-06.html
@@ -1,182 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<meta name="viewport" content="width=device-width">
|
||||
|
||||
<title>GB-2015-06: Corrections to Autobridging - Ripple Developer Portal</title>
|
||||
|
||||
<!-- favicon -->
|
||||
<link rel="icon" href="favicon.ico" type="image/x-icon">
|
||||
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon">
|
||||
|
||||
<!-- jQuery -->
|
||||
<script src="assets/vendor/jquery-1.11.1.min.js"></script>
|
||||
|
||||
<!-- Custom Stylesheets. ripple.css includes bootstrap, font stuff -->
|
||||
<link href="assets/css/ripple.css" rel="stylesheet" />
|
||||
<link href="assets/css/devportal.css" rel="stylesheet" />
|
||||
|
||||
<!-- Bootstrap JS -->
|
||||
<script src="assets/vendor/bootstrap.min.js"></script>
|
||||
|
||||
|
||||
<!-- syntax highlighting -->
|
||||
<link rel="stylesheet" href="assets/vendor/docco.min.css" />
|
||||
<script src="assets/vendor/highlight.min.js"></script>
|
||||
|
||||
<!-- syntax selection js -->
|
||||
<script src="assets/js/multicodetab.js"></script>
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
$(".multicode").minitabs();
|
||||
hljs.initHighlighting();
|
||||
make_code_expandable();
|
||||
});
|
||||
</script>
|
||||
|
||||
<script src="assets/js/expandcode.js"></script>
|
||||
<script src="assets/js/fixsidebarscroll.js"></script>
|
||||
|
||||
<!-- fontawesome icons -->
|
||||
<link rel="stylesheet" href="assets/vendor/fontawesome/css/font-awesome.min.css" />
|
||||
|
||||
</head>
|
||||
|
||||
<body class="page page-template page-template-template-dev-portal page-template-template-dev-portal-php sidebar-primary wpb-js-composer js-comp-ver-3.6.2 vc_responsive">
|
||||
<header role="banner" class="banner navbar navbar-default navbar-fixed-top initial_header">
|
||||
<div class="container">
|
||||
<div class="navbar-header">
|
||||
<a href="index.html" class="navbar-brand"><img src="assets/img/ripple-logo-color.png" class="logo"></a>
|
||||
</div><!-- /.navbar-header -->
|
||||
<div class="nav">
|
||||
<div class="draft-warning">DRAFT PAGE</div>
|
||||
</div><!-- /.nav -->
|
||||
|
||||
</div><!-- /.container -->
|
||||
|
||||
<div class="subnav dev_nav">
|
||||
<div class="container">
|
||||
<ul id="menu-dev-menu" class="menu">
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">References <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="reference-rippleapi.html">RippleAPI</a></li>
|
||||
<li><a href="reference-rippled.html">rippled</a></li>
|
||||
<li><a href="reference-transaction-format.html">Transaction Format</a></li>
|
||||
<li><a href="reference-ledger-format.html">Ledger Format</a></li>
|
||||
<li><a href="reference-data-api.html">Ripple Data API v2</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorials <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="tutorial-multisign.html">How to Multi-Sign</a></li>
|
||||
<li><a href="tutorial-paychan.html">Payment Channels Tutorial</a></li>
|
||||
<li><a href="concept-issuing-and-operational-addresses.html">Issuing and Operational Addresses</a></li>
|
||||
<li><a href="tutorial-reliable-transaction-submission.html">Reliable Transaction Submission</a></li>
|
||||
<li><a href="tutorial-rippleapi-beginners-guide.html">RippleAPI Beginners Guide</a></li>
|
||||
<li><a href="tutorial-rippled-setup.html">rippled Setup</a></li>
|
||||
<li><a href="tutorial-gateway-guide.html">Gateway Guide</a></li>
|
||||
<li><a href="tutorial-listing-xrp.html">Listing XRP as an Exchange</a></li>
|
||||
<li><a href="tutorial-escrow.html">Escrow Tutorials</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Features <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="concept-accounts.html">Accounts</a></li>
|
||||
<li><a href="concept-amendments.html">Amendments</a></li>
|
||||
<li><a href="concept-consensus.html">Consensus Process</a></li>
|
||||
<li><a href="concept-reaching-consensus.html">Reaching Consensus in the XRP Ledger</a></li>
|
||||
<li><a href="concept-fee-voting.html">Fee Voting</a></li>
|
||||
<li><a href="concept-fees.html">Fees (Disambiguation)</a></li>
|
||||
<li><a href="concept-freeze.html">Freeze</a></li>
|
||||
<li><a href="concept-partial-payments.html">Partial Payments</a></li>
|
||||
<li><a href="concept-paths.html">Paths</a></li>
|
||||
<li><a href="concept-reserves.html">Reserves</a></li>
|
||||
<li><a href="concept-stand-alone-mode.html">Stand-Alone Mode</a></li>
|
||||
<li><a href="concept-transaction-cost.html">Transaction Cost</a></li>
|
||||
<li><a href="concept-transfer-fees.html">Transfer Fees</a></li>
|
||||
<li><a href="concept-noripple.html">Understanding the NoRipple flag</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Gateway Bulletins <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="gb-2015-06.html">GB-2015-06: Corrections to Autobridging</a></li>
|
||||
<li><a href="gb-2015-05.html">GB-2015-05: Historical Ledger Query Migration</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">API Tools <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="ripple-api-tool.html">WebSocket API Tool</a></li>
|
||||
<li><a href="data-api-v2-tool.html">Data API v2 Tool</a></li>
|
||||
<li><a href="tool-jsonrpc.html">rippled JSON-RPC Tool</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li><a href="https://github.com/ripple/ripple-dev-portal" title="GitHub">Site Source</a></li>
|
||||
</ul><!-- /#dev-menu -->
|
||||
</div><!-- /.subnav .container -->
|
||||
</div><!-- /.subnav -->
|
||||
</header>
|
||||
|
||||
|
||||
<div class="wrap container" role="document">
|
||||
<aside class="sidebar" role="complementary">
|
||||
<div class="dev_nav_wrapper">
|
||||
<div id="cont">
|
||||
<h5>In this category:</h5>
|
||||
<ul class="dev_nav_sidebar">
|
||||
<li class="level-1"><a href="index.html">Category: Gateway Bulletins</a></li>
|
||||
<li class="level-2"><a href="gb-2015-06.html">GB-2015-06: Corrections to Autobridging</a></li>
|
||||
<li class="level-2"><a href="gb-2015-05.html">GB-2015-05: Historical Ledger Query Migration</a></li>
|
||||
</ul>
|
||||
<hr />
|
||||
<h5>In this page:</h5>
|
||||
<ul class="dev_nav_sidebar" id="dactyl_toc_sidebar">
|
||||
<li class="level-1"><a href="#gb-2015-06-corrections-to-autobridging">GB-2015-06: Corrections to Autobridging</a></li>
|
||||
<li class="level-2"><a href="#overview">Overview</a></li>
|
||||
<li class="level-2"><a href="#additional-resources">Additional Resources</a></li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
<main class="main" role="main">
|
||||
<div class='content'>
|
||||
<h1 id="gb-2015-06-corrections-to-autobridging">GB-2015-06: Corrections to Autobridging</h1>
|
||||
<h2 id="overview">Overview</h2>
|
||||
<p>Ripple Labs recently deployed a new feature to the Ripple network called autobridging. An error in the autobridging implementation caused some gateways to erroneously hold small balances. This error has been corrected. The total value miscredited across the Ripple network as a result of this error was less than $10.</p>
|
||||
<p>Ripple Labs recommends gateways forgive these small errors. A gateway can forgive these errors by auditing their cold wallet balances for unwanted positive values and then using a payment transaction to zero those positive balances. This has the benefit of (1) the gateway not holding unwanted 3rd party balances in their cold wallet and (2) simplifying future audits by eliminating unnecessary balances.</p>
|
||||
<p>The fix is currently deployed and may cause rippled servers not running the latest release to reacquire sync slightly more often than normal. Optionally, to avoid unnecessary resyncs, rippled servers can be upgraded to the latest release:</p>
|
||||
<p><a href="https://github.com/ripple/rippled/releases/tag/0.28.1-rc2">0.28.1-rc2</a></p>
|
||||
<p>The latest release of rippled can be found on Github.</p>
|
||||
<h2 id="additional-resources">Additional Resources</h2>
|
||||
<ul>
|
||||
<li>Learn more about <a href="https://ripple.com/blog/rippled-feature-update-nudb-and-autobridging/">Autobridging</a></li>
|
||||
<li>For assistance, contact: <a href="mailto:support@ripple.com">support@ripple.com</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<footer class="content-info" role="contentinfo">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-sm-12 absolute_bottom_footer">
|
||||
<div class="col-sm-8">
|
||||
<span>© 2013 - 2017 Ripple Labs, Inc. All Rights Reserved.</span>
|
||||
<span><a href="/terms-of-use/">Terms</a></span>
|
||||
<span><a href="/privacy-policy/">Privacy</a></span>
|
||||
</div>
|
||||
</div><!-- /.absolute_bottom_footer -->
|
||||
|
||||
</div><!-- /.row -->
|
||||
</div><!-- /.container -->
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
224
index.html
224
index.html
@@ -1,224 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<meta name="viewport" content="width=device-width">
|
||||
|
||||
<title>Overview - Ripple Developer Portal</title>
|
||||
|
||||
<!-- favicon -->
|
||||
<link rel="icon" href="favicon.ico" type="image/x-icon">
|
||||
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon">
|
||||
|
||||
<!-- jQuery -->
|
||||
<script src="assets/vendor/jquery-1.11.1.min.js"></script>
|
||||
|
||||
<!-- Custom Stylesheets. ripple.css includes bootstrap, font stuff -->
|
||||
<link href="assets/css/ripple.css" rel="stylesheet" />
|
||||
<link href="assets/css/devportal.css" rel="stylesheet" />
|
||||
|
||||
<!-- Bootstrap JS -->
|
||||
<script src="assets/vendor/bootstrap.min.js"></script>
|
||||
|
||||
|
||||
<!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
|
||||
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
|
||||
<!--[if lt IE 9]>
|
||||
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
|
||||
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
|
||||
<![endif]-->
|
||||
|
||||
|
||||
<link href="assets/css/landing.css" rel="stylesheet">
|
||||
|
||||
|
||||
</head>
|
||||
|
||||
<body class="page page-template page-template-template-dev-portal page-template-template-dev-portal-php wpb-js-composer js-comp-ver-3.6.2 vc_responsive">
|
||||
<header role="banner" class="banner navbar navbar-default navbar-fixed-top initial_header">
|
||||
<div class="container">
|
||||
<div class="navbar-header">
|
||||
<a href="index.html" class="navbar-brand"><img src="assets/img/ripple-logo-color.png" class="logo"></a>
|
||||
</div><!-- /.navbar-header -->
|
||||
<div class="nav">
|
||||
<div class="draft-warning">DRAFT PAGE</div>
|
||||
</div><!-- /.nav -->
|
||||
|
||||
</div><!-- /.container -->
|
||||
|
||||
<div class="subnav dev_nav">
|
||||
<div class="container">
|
||||
<ul id="menu-dev-menu" class="menu">
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">References <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="reference-rippleapi.html">RippleAPI</a></li>
|
||||
<li><a href="reference-rippled.html">rippled</a></li>
|
||||
<li><a href="reference-transaction-format.html">Transaction Format</a></li>
|
||||
<li><a href="reference-ledger-format.html">Ledger Format</a></li>
|
||||
<li><a href="reference-data-api.html">Ripple Data API v2</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorials <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="tutorial-multisign.html">How to Multi-Sign</a></li>
|
||||
<li><a href="tutorial-paychan.html">Payment Channels Tutorial</a></li>
|
||||
<li><a href="concept-issuing-and-operational-addresses.html">Issuing and Operational Addresses</a></li>
|
||||
<li><a href="tutorial-reliable-transaction-submission.html">Reliable Transaction Submission</a></li>
|
||||
<li><a href="tutorial-rippleapi-beginners-guide.html">RippleAPI Beginners Guide</a></li>
|
||||
<li><a href="tutorial-rippled-setup.html">rippled Setup</a></li>
|
||||
<li><a href="tutorial-gateway-guide.html">Gateway Guide</a></li>
|
||||
<li><a href="tutorial-listing-xrp.html">Listing XRP as an Exchange</a></li>
|
||||
<li><a href="tutorial-escrow.html">Escrow Tutorials</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Features <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="concept-accounts.html">Accounts</a></li>
|
||||
<li><a href="concept-amendments.html">Amendments</a></li>
|
||||
<li><a href="concept-consensus.html">Consensus Process</a></li>
|
||||
<li><a href="concept-reaching-consensus.html">Reaching Consensus in the XRP Ledger</a></li>
|
||||
<li><a href="concept-fee-voting.html">Fee Voting</a></li>
|
||||
<li><a href="concept-fees.html">Fees (Disambiguation)</a></li>
|
||||
<li><a href="concept-freeze.html">Freeze</a></li>
|
||||
<li><a href="concept-partial-payments.html">Partial Payments</a></li>
|
||||
<li><a href="concept-paths.html">Paths</a></li>
|
||||
<li><a href="concept-reserves.html">Reserves</a></li>
|
||||
<li><a href="concept-stand-alone-mode.html">Stand-Alone Mode</a></li>
|
||||
<li><a href="concept-transaction-cost.html">Transaction Cost</a></li>
|
||||
<li><a href="concept-transfer-fees.html">Transfer Fees</a></li>
|
||||
<li><a href="concept-noripple.html">Understanding the NoRipple flag</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Gateway Bulletins <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="gb-2015-06.html">GB-2015-06: Corrections to Autobridging</a></li>
|
||||
<li><a href="gb-2015-05.html">GB-2015-05: Historical Ledger Query Migration</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">API Tools <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="ripple-api-tool.html">WebSocket API Tool</a></li>
|
||||
<li><a href="data-api-v2-tool.html">Data API v2 Tool</a></li>
|
||||
<li><a href="tool-jsonrpc.html">rippled JSON-RPC Tool</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li><a href="https://github.com/ripple/ripple-dev-portal" title="GitHub">Site Source</a></li>
|
||||
</ul><!-- /#dev-menu -->
|
||||
</div><!-- /.subnav .container -->
|
||||
</div><!-- /.subnav -->
|
||||
</header>
|
||||
|
||||
|
||||
<div class="wrap container" role="document">
|
||||
<main class="main" role="main">
|
||||
|
||||
<!-- jumbotron -->
|
||||
<!-- <div class="container theme-showcase" role="main"> -->
|
||||
<div class="jumbotron">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="col-md-3">
|
||||
<img class="large_logo" src="assets/img/dev-logo.png" />
|
||||
</div>
|
||||
<div class="col-md-9">
|
||||
<h4>Welcome to the Developer Center</h4>
|
||||
<p class="main_callout">
|
||||
Ripple’s distributed settlement network is built on open-source technology that anyone can use. Here are the tools developers can use to build solutions around the open-source platform.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- </div> -->
|
||||
|
||||
<!-- main container -->
|
||||
<div class="container build-index">
|
||||
<div class="row">
|
||||
<div class="col-md-3">
|
||||
<ul>
|
||||
<li class="top"><h5 class="dev_heading">References</h5></li>
|
||||
<li><a href="reference-rippleapi.html">RippleAPI</a></li>
|
||||
<li><a href="reference-rippled.html">rippled</a></li>
|
||||
<li><a href="reference-transaction-format.html">Transaction Format</a></li>
|
||||
<li><a href="reference-ledger-format.html">Ledger Format</a></li>
|
||||
<li><a href="reference-data-api.html">Ripple Data API v2</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<ul>
|
||||
<li class="top"><h5 class="dev_heading">Tutorials</h5></li>
|
||||
<li><a href="tutorial-multisign.html">How to Multi-Sign</a></li>
|
||||
<li><a href="tutorial-paychan.html">Payment Channels Tutorial</a></li>
|
||||
<li><a href="concept-issuing-and-operational-addresses.html">Issuing and Operational Addresses</a></li>
|
||||
<li><a href="tutorial-reliable-transaction-submission.html">Reliable Transaction Submission</a></li>
|
||||
<li><a href="tutorial-rippleapi-beginners-guide.html">RippleAPI Beginners Guide</a></li>
|
||||
<li><a href="tutorial-rippled-setup.html">rippled Setup</a></li>
|
||||
<li><a href="tutorial-gateway-guide.html">Gateway Guide</a></li>
|
||||
<li><a href="tutorial-listing-xrp.html">Listing XRP as an Exchange</a></li>
|
||||
<li><a href="tutorial-escrow.html">Escrow Tutorials</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<ul>
|
||||
<li class="top"><h5 class="dev_heading">Features</h5></li>
|
||||
<li><a href="concept-accounts.html">Accounts</a></li>
|
||||
<li><a href="concept-amendments.html">Amendments</a></li>
|
||||
<li><a href="concept-consensus.html">Consensus Process</a></li>
|
||||
<li><a href="concept-reaching-consensus.html">Reaching Consensus in the XRP Ledger</a></li>
|
||||
<li><a href="concept-fee-voting.html">Fee Voting</a></li>
|
||||
<li><a href="concept-fees.html">Fees (Disambiguation)</a></li>
|
||||
<li><a href="concept-freeze.html">Freeze</a></li>
|
||||
<li><a href="concept-partial-payments.html">Partial Payments</a></li>
|
||||
<li><a href="concept-paths.html">Paths</a></li>
|
||||
<li><a href="concept-reserves.html">Reserves</a></li>
|
||||
<li><a href="concept-stand-alone-mode.html">Stand-Alone Mode</a></li>
|
||||
<li><a href="concept-transaction-cost.html">Transaction Cost</a></li>
|
||||
<li><a href="concept-transfer-fees.html">Transfer Fees</a></li>
|
||||
<li><a href="concept-noripple.html">Understanding the NoRipple flag</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<ul>
|
||||
<li class="top"><h5 class="dev_heading">Gateway Bulletins</h5></li>
|
||||
<li><a href="gb-2015-06.html">GB-2015-06: Corrections to Autobridging</a></li>
|
||||
<li><a href="gb-2015-05.html">GB-2015-05: Historical Ledger Query Migration</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<ul>
|
||||
<li class="top"><h5 class="dev_heading">API Tools</h5></li>
|
||||
<li><a href="ripple-api-tool.html">WebSocket API Tool</a></li>
|
||||
<li><a href="data-api-v2-tool.html">Data API v2 Tool</a></li>
|
||||
<li><a href="tool-jsonrpc.html">rippled JSON-RPC Tool</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<footer class="content-info" role="contentinfo">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-sm-12 absolute_bottom_footer">
|
||||
<div class="col-sm-8">
|
||||
<span>© 2013 - 2017 Ripple Labs, Inc. All Rights Reserved.</span>
|
||||
<span><a href="/terms-of-use/">Terms</a></span>
|
||||
<span><a href="/privacy-policy/">Privacy</a></span>
|
||||
</div>
|
||||
</div><!-- /.absolute_bottom_footer -->
|
||||
|
||||
</div><!-- /.row -->
|
||||
</div><!-- /.container -->
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
13826
reference-rippled.html
13826
reference-rippled.html
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,211 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<meta name="viewport" content="width=device-width">
|
||||
|
||||
<title>WebSocket API Tool - Ripple Developer Portal</title>
|
||||
|
||||
<!-- favicon -->
|
||||
<link rel="icon" href="favicon.ico" type="image/x-icon">
|
||||
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon">
|
||||
|
||||
<!-- jQuery -->
|
||||
<script src="assets/vendor/jquery-1.11.1.min.js"></script>
|
||||
|
||||
<!-- Custom Stylesheets. ripple.css includes bootstrap, font stuff -->
|
||||
<link href="assets/css/ripple.css" rel="stylesheet" />
|
||||
<link href="assets/css/devportal.css" rel="stylesheet" />
|
||||
|
||||
<!-- Bootstrap JS -->
|
||||
<script src="assets/vendor/bootstrap.min.js"></script>
|
||||
|
||||
|
||||
|
||||
</head>
|
||||
|
||||
<body class="page page-template page-template-template-dev-portal page-template-template-dev-portal-php sidebar-primary wpb-js-composer js-comp-ver-3.6.2 vc_responsive">
|
||||
<header role="banner" class="banner navbar navbar-default navbar-fixed-top initial_header">
|
||||
<div class="container">
|
||||
<div class="navbar-header">
|
||||
<a href="index.html" class="navbar-brand"><img src="assets/img/ripple-logo-color.png" class="logo"></a>
|
||||
</div><!-- /.navbar-header -->
|
||||
<div class="nav">
|
||||
<div class="draft-warning">DRAFT PAGE</div>
|
||||
</div><!-- /.nav -->
|
||||
|
||||
</div><!-- /.container -->
|
||||
|
||||
<div class="subnav dev_nav">
|
||||
<div class="container">
|
||||
<ul id="menu-dev-menu" class="menu">
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">References <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="reference-rippleapi.html">RippleAPI</a></li>
|
||||
<li><a href="reference-rippled.html">rippled</a></li>
|
||||
<li><a href="reference-transaction-format.html">Transaction Format</a></li>
|
||||
<li><a href="reference-ledger-format.html">Ledger Format</a></li>
|
||||
<li><a href="reference-data-api.html">Ripple Data API v2</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorials <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="tutorial-multisign.html">How to Multi-Sign</a></li>
|
||||
<li><a href="tutorial-paychan.html">Payment Channels Tutorial</a></li>
|
||||
<li><a href="concept-issuing-and-operational-addresses.html">Issuing and Operational Addresses</a></li>
|
||||
<li><a href="tutorial-reliable-transaction-submission.html">Reliable Transaction Submission</a></li>
|
||||
<li><a href="tutorial-rippleapi-beginners-guide.html">RippleAPI Beginners Guide</a></li>
|
||||
<li><a href="tutorial-rippled-setup.html">rippled Setup</a></li>
|
||||
<li><a href="tutorial-gateway-guide.html">Gateway Guide</a></li>
|
||||
<li><a href="tutorial-listing-xrp.html">Listing XRP as an Exchange</a></li>
|
||||
<li><a href="tutorial-escrow.html">Escrow Tutorials</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Features <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="concept-accounts.html">Accounts</a></li>
|
||||
<li><a href="concept-amendments.html">Amendments</a></li>
|
||||
<li><a href="concept-consensus.html">Consensus Process</a></li>
|
||||
<li><a href="concept-reaching-consensus.html">Reaching Consensus in the XRP Ledger</a></li>
|
||||
<li><a href="concept-fee-voting.html">Fee Voting</a></li>
|
||||
<li><a href="concept-fees.html">Fees (Disambiguation)</a></li>
|
||||
<li><a href="concept-freeze.html">Freeze</a></li>
|
||||
<li><a href="concept-partial-payments.html">Partial Payments</a></li>
|
||||
<li><a href="concept-paths.html">Paths</a></li>
|
||||
<li><a href="concept-reserves.html">Reserves</a></li>
|
||||
<li><a href="concept-stand-alone-mode.html">Stand-Alone Mode</a></li>
|
||||
<li><a href="concept-transaction-cost.html">Transaction Cost</a></li>
|
||||
<li><a href="concept-transfer-fees.html">Transfer Fees</a></li>
|
||||
<li><a href="concept-noripple.html">Understanding the NoRipple flag</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Gateway Bulletins <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="gb-2015-06.html">GB-2015-06: Corrections to Autobridging</a></li>
|
||||
<li><a href="gb-2015-05.html">GB-2015-05: Historical Ledger Query Migration</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">API Tools <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="ripple-api-tool.html">WebSocket API Tool</a></li>
|
||||
<li><a href="data-api-v2-tool.html">Data API v2 Tool</a></li>
|
||||
<li><a href="tool-jsonrpc.html">rippled JSON-RPC Tool</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li><a href="https://github.com/ripple/ripple-dev-portal" title="GitHub">Site Source</a></li>
|
||||
</ul><!-- /#dev-menu -->
|
||||
</div><!-- /.subnav .container -->
|
||||
</div><!-- /.subnav -->
|
||||
</header>
|
||||
|
||||
|
||||
<div class="wrap container" role="document">
|
||||
<aside class="sidebar" role="complementary">
|
||||
<ul id='command_list'>
|
||||
<li class='selected'><a href='#server_info'>server_info</a></li>
|
||||
<li><a href='#server_state'>server_state</a></li>
|
||||
<li><a href='#ping'>ping</a></li>
|
||||
<br/>
|
||||
<li><a href='#subscribe'>subscribe</a></li>
|
||||
<li><a href='#unsubscribe'>unsubscribe</a></li>
|
||||
<br/>
|
||||
<li><a href='#ledger'>ledger</a></li>
|
||||
<li><a href='#ledger_closed'>ledger_closed</a></li>
|
||||
<li><a href='#ledger_current'>ledger_current</a></li>
|
||||
<li><a href='#ledger_entry'>ledger_entry</a></li>
|
||||
<br/>
|
||||
<li><a href='#account_info'>account_info</a></li>
|
||||
<li><a href='#account_lines'>account_lines</a></li>
|
||||
<li><a href='#account_offers'>account_offers</a></li>
|
||||
<li><a href='#account_tx'>account_tx</a></li>
|
||||
<li><a href='#account_currencies'>account_currencies</a></li>
|
||||
<br/>
|
||||
<li><a href='#transaction_entry'>transaction_entry</a></li>
|
||||
<li><a href='#tx'>tx</a></li>
|
||||
<li><a href='#tx_history'>tx_history</a></li>
|
||||
<br/>
|
||||
<li><a href='#sign'>sign</a></li>
|
||||
<li><a href='#submit'>submit</a></li>
|
||||
<br/>
|
||||
<li><a href='#ripple_path_find'>ripple_path_find</a></li>
|
||||
<li><a href='#path_find'>path_find</a></li>
|
||||
<li><a href='#book_offers'>book_offers</a></li>
|
||||
</ul>
|
||||
</aside>
|
||||
<main class="main" role="main">
|
||||
<div class='content-root'>
|
||||
<div id='online_state'>Offline</div>
|
||||
<div style="clear:both;"></div>
|
||||
<div id='command_wrapper'>
|
||||
<div id='command_table'>
|
||||
<div id='io_wrapper'>
|
||||
<div id='input' class='io'>
|
||||
<h2>WebSocket Request</h2>
|
||||
<div id='test_warning' class='alert alert-danger' style='display:none;'>
|
||||
<h4>Test accounts only!</h4>
|
||||
<p>Never submit account secrets to a server you do not control, unless you are prepared to lose ownership of the account!</p>
|
||||
</div>
|
||||
<div style="clear:both;"></div>
|
||||
<h3 id='selected_command' title='Reference information'>server_info</h3>
|
||||
<p id='description'></p>
|
||||
<div id='invalid'>Invalid JSON</div>
|
||||
<p>JSON</p>
|
||||
<div id='request'></div>
|
||||
<div id='request_options'>
|
||||
<div class="button btn btn-primary api" id='request_button'>Send request</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id='output' class='io'>
|
||||
<h2>Response</h2>
|
||||
<div>
|
||||
<img class="loader" src="assets/img/rippleThrobber.png" style="vertical-align: middle; display:none;"/>
|
||||
</div>
|
||||
<p id='info'></p>
|
||||
<div id='response'></div>
|
||||
<div id='tooltip'></div>
|
||||
<div id='stream_output'>
|
||||
<h3>Stream output</h3>
|
||||
<ul class='toolbar'>
|
||||
<li id='stream_show'>show</li>
|
||||
<li id='stream_pause'>pause</li>
|
||||
</ul>
|
||||
<p id='status'></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<footer class="content-info" role="contentinfo">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-sm-12 absolute_bottom_footer">
|
||||
<div class="col-sm-8">
|
||||
<span>© 2013 - 2017 Ripple Labs, Inc. All Rights Reserved.</span>
|
||||
<span><a href="/terms-of-use/">Terms</a></span>
|
||||
<span><a href="/privacy-policy/">Privacy</a></span>
|
||||
</div>
|
||||
</div><!-- /.absolute_bottom_footer -->
|
||||
|
||||
</div><!-- /.row -->
|
||||
</div><!-- /.container -->
|
||||
</footer>
|
||||
<link rel='stylesheet' type='text/css' href='assets/css/api-tools.css'/>
|
||||
<link rel='stylesheet' type='text/css' href='assets/vendor/codemirror.css'/>
|
||||
<script type='text/javascript' src='assets/js/es5-shim.js'></script>
|
||||
<script type='text/javascript' src='assets/vendor/codemirror.min.js'></script>
|
||||
<script type='text/javascript' src='assets/vendor/cm-javascript.min.js'></script>
|
||||
<script type='text/javascript' src='assets/js/ripple-0.11.0-min.js'></script>
|
||||
<script type='text/javascript' src='assets/js/apitool-websocket.js'></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,184 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<meta name="viewport" content="width=device-width">
|
||||
|
||||
<title>rippled JSON-RPC Tool - Ripple Developer Portal</title>
|
||||
|
||||
<!-- favicon -->
|
||||
<link rel="icon" href="favicon.ico" type="image/x-icon">
|
||||
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon">
|
||||
|
||||
<!-- jQuery -->
|
||||
<script src="assets/vendor/jquery-1.11.1.min.js"></script>
|
||||
|
||||
<!-- Custom Stylesheets. ripple.css includes bootstrap, font stuff -->
|
||||
<link href="assets/css/ripple.css" rel="stylesheet" />
|
||||
<link href="assets/css/devportal.css" rel="stylesheet" />
|
||||
|
||||
<!-- Bootstrap JS -->
|
||||
<script src="assets/vendor/bootstrap.min.js"></script>
|
||||
|
||||
|
||||
|
||||
</head>
|
||||
|
||||
<body class="page page-template page-template-template-dev-portal page-template-template-dev-portal-php sidebar-primary wpb-js-composer js-comp-ver-3.6.2 vc_responsive">
|
||||
<header role="banner" class="banner navbar navbar-default navbar-fixed-top initial_header">
|
||||
<div class="container">
|
||||
<div class="navbar-header">
|
||||
<a href="index.html" class="navbar-brand"><img src="assets/img/ripple-logo-color.png" class="logo"></a>
|
||||
</div><!-- /.navbar-header -->
|
||||
<div class="nav">
|
||||
<div class="draft-warning">DRAFT PAGE</div>
|
||||
</div><!-- /.nav -->
|
||||
|
||||
</div><!-- /.container -->
|
||||
|
||||
<div class="subnav dev_nav">
|
||||
<div class="container">
|
||||
<ul id="menu-dev-menu" class="menu">
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">References <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="reference-rippleapi.html">RippleAPI</a></li>
|
||||
<li><a href="reference-rippled.html">rippled</a></li>
|
||||
<li><a href="reference-transaction-format.html">Transaction Format</a></li>
|
||||
<li><a href="reference-ledger-format.html">Ledger Format</a></li>
|
||||
<li><a href="reference-data-api.html">Ripple Data API v2</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorials <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="tutorial-multisign.html">How to Multi-Sign</a></li>
|
||||
<li><a href="tutorial-paychan.html">Payment Channels Tutorial</a></li>
|
||||
<li><a href="concept-issuing-and-operational-addresses.html">Issuing and Operational Addresses</a></li>
|
||||
<li><a href="tutorial-reliable-transaction-submission.html">Reliable Transaction Submission</a></li>
|
||||
<li><a href="tutorial-rippleapi-beginners-guide.html">RippleAPI Beginners Guide</a></li>
|
||||
<li><a href="tutorial-rippled-setup.html">rippled Setup</a></li>
|
||||
<li><a href="tutorial-gateway-guide.html">Gateway Guide</a></li>
|
||||
<li><a href="tutorial-listing-xrp.html">Listing XRP as an Exchange</a></li>
|
||||
<li><a href="tutorial-escrow.html">Escrow Tutorials</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Features <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="concept-accounts.html">Accounts</a></li>
|
||||
<li><a href="concept-amendments.html">Amendments</a></li>
|
||||
<li><a href="concept-consensus.html">Consensus Process</a></li>
|
||||
<li><a href="concept-reaching-consensus.html">Reaching Consensus in the XRP Ledger</a></li>
|
||||
<li><a href="concept-fee-voting.html">Fee Voting</a></li>
|
||||
<li><a href="concept-fees.html">Fees (Disambiguation)</a></li>
|
||||
<li><a href="concept-freeze.html">Freeze</a></li>
|
||||
<li><a href="concept-partial-payments.html">Partial Payments</a></li>
|
||||
<li><a href="concept-paths.html">Paths</a></li>
|
||||
<li><a href="concept-reserves.html">Reserves</a></li>
|
||||
<li><a href="concept-stand-alone-mode.html">Stand-Alone Mode</a></li>
|
||||
<li><a href="concept-transaction-cost.html">Transaction Cost</a></li>
|
||||
<li><a href="concept-transfer-fees.html">Transfer Fees</a></li>
|
||||
<li><a href="concept-noripple.html">Understanding the NoRipple flag</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Gateway Bulletins <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="gb-2015-06.html">GB-2015-06: Corrections to Autobridging</a></li>
|
||||
<li><a href="gb-2015-05.html">GB-2015-05: Historical Ledger Query Migration</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">API Tools <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="ripple-api-tool.html">WebSocket API Tool</a></li>
|
||||
<li><a href="data-api-v2-tool.html">Data API v2 Tool</a></li>
|
||||
<li><a href="tool-jsonrpc.html">rippled JSON-RPC Tool</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li><a href="https://github.com/ripple/ripple-dev-portal" title="GitHub">Site Source</a></li>
|
||||
</ul><!-- /#dev-menu -->
|
||||
</div><!-- /.subnav .container -->
|
||||
</div><!-- /.subnav -->
|
||||
</header>
|
||||
|
||||
|
||||
<div class="wrap container" role="document">
|
||||
<aside class="sidebar" role="complementary">
|
||||
<ul id='command_list'>
|
||||
</ul>
|
||||
</aside>
|
||||
<main class="main" role="main">
|
||||
<div id='wrapper'>
|
||||
<div style="clear:both;"></div>
|
||||
<div id='command_wrapper'>
|
||||
<div id='command_table'>
|
||||
<div id='io_wrapper'>
|
||||
<div id='input' class='io'>
|
||||
<h2>REST Request</h2>
|
||||
<div id='test_warning' class='alert alert-danger' style='display:none;'>
|
||||
<h4>Test accounts only!</h4>
|
||||
<p>Never submit account secrets to a server you do not control, unless you are prepared to lose ownership of the account!</p>
|
||||
</div>
|
||||
<div style="clear:both;"></div>
|
||||
<h3 id='selected_command' title='Reference information'></h3>
|
||||
<p id='description'></p>
|
||||
<div id='invalid'>Invalid JSON</div>
|
||||
<div id='rest_url_wrapper'>
|
||||
<p><span id='rest_host'>http://localhost/rippled</span><span id='rest_url'></span></p>
|
||||
</div>
|
||||
<div id='request_body'></div>
|
||||
<div id='request_options'>
|
||||
<a class="button btn btn-primary api" id='request_button'>Send request</a>
|
||||
</div>
|
||||
</div>
|
||||
<div id='output' class='io'>
|
||||
<h2>Response</h2>
|
||||
<div>
|
||||
<img class="loader" src="assets/img/rippleThrobber.png" style="vertical-align: middle; display:none;"/>
|
||||
<span id='rest_responsecode'></span>
|
||||
</div>
|
||||
<div id='response_body'></div>
|
||||
<div id='tooltip'></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script type='text/javascript'>
|
||||
// Set some constants for the REST tool script
|
||||
var URL_BASE = 'http://localhost/rippled';
|
||||
var DOC_BASE = 'reference-rippled.html';
|
||||
</script>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<footer class="content-info" role="contentinfo">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-sm-12 absolute_bottom_footer">
|
||||
<div class="col-sm-8">
|
||||
<span>© 2013 - 2017 Ripple Labs, Inc. All Rights Reserved.</span>
|
||||
<span><a href="/terms-of-use/">Terms</a></span>
|
||||
<span><a href="/privacy-policy/">Privacy</a></span>
|
||||
</div>
|
||||
</div><!-- /.absolute_bottom_footer -->
|
||||
|
||||
</div><!-- /.row -->
|
||||
</div><!-- /.container -->
|
||||
</footer>
|
||||
|
||||
<link rel='stylesheet' type='text/css' href='assets/css/api-tools.css'/>
|
||||
<link rel='stylesheet' type='text/css' href='assets/vendor/codemirror.css'/>
|
||||
<script type='text/javascript' src='assets/js/es5-shim.js'></script>
|
||||
<script type='text/javascript' src='assets/vendor/codemirror.min.js'></script>
|
||||
<script type='text/javascript' src='assets/vendor/cm-javascript.min.js'></script>
|
||||
<script type='text/javascript' src='assets/js/jquery.autosize.input.min.js'></script>
|
||||
<script type='text/javascript' src='assets/js/apitool-rest.js'></script>
|
||||
<script type='text/javascript' src='assets/js/apitool-methods-jsonrpc.js'></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,972 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<meta name="viewport" content="width=device-width">
|
||||
|
||||
<title>Escrow Tutorials - Ripple Developer Portal</title>
|
||||
|
||||
<!-- favicon -->
|
||||
<link rel="icon" href="favicon.ico" type="image/x-icon">
|
||||
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon">
|
||||
|
||||
<!-- jQuery -->
|
||||
<script src="assets/vendor/jquery-1.11.1.min.js"></script>
|
||||
|
||||
<!-- Custom Stylesheets. ripple.css includes bootstrap, font stuff -->
|
||||
<link href="assets/css/ripple.css" rel="stylesheet" />
|
||||
<link href="assets/css/devportal.css" rel="stylesheet" />
|
||||
|
||||
<!-- Bootstrap JS -->
|
||||
<script src="assets/vendor/bootstrap.min.js"></script>
|
||||
|
||||
|
||||
<!-- syntax highlighting -->
|
||||
<link rel="stylesheet" href="assets/vendor/docco.min.css" />
|
||||
<script src="assets/vendor/highlight.min.js"></script>
|
||||
|
||||
<!-- syntax selection js -->
|
||||
<script src="assets/js/multicodetab.js"></script>
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
$(".multicode").minitabs();
|
||||
hljs.initHighlighting();
|
||||
make_code_expandable();
|
||||
});
|
||||
</script>
|
||||
|
||||
<script src="assets/js/expandcode.js"></script>
|
||||
<script src="assets/js/fixsidebarscroll.js"></script>
|
||||
|
||||
<!-- fontawesome icons -->
|
||||
<link rel="stylesheet" href="assets/vendor/fontawesome/css/font-awesome.min.css" />
|
||||
|
||||
</head>
|
||||
|
||||
<body class="page page-template page-template-template-dev-portal page-template-template-dev-portal-php sidebar-primary wpb-js-composer js-comp-ver-3.6.2 vc_responsive">
|
||||
<header role="banner" class="banner navbar navbar-default navbar-fixed-top initial_header">
|
||||
<div class="container">
|
||||
<div class="navbar-header">
|
||||
<a href="index.html" class="navbar-brand"><img src="assets/img/ripple-logo-color.png" class="logo"></a>
|
||||
</div><!-- /.navbar-header -->
|
||||
<div class="nav">
|
||||
<div class="draft-warning">DRAFT PAGE</div>
|
||||
</div><!-- /.nav -->
|
||||
|
||||
</div><!-- /.container -->
|
||||
|
||||
<div class="subnav dev_nav">
|
||||
<div class="container">
|
||||
<ul id="menu-dev-menu" class="menu">
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">References <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="reference-rippleapi.html">RippleAPI</a></li>
|
||||
<li><a href="reference-rippled.html">rippled</a></li>
|
||||
<li><a href="reference-transaction-format.html">Transaction Format</a></li>
|
||||
<li><a href="reference-ledger-format.html">Ledger Format</a></li>
|
||||
<li><a href="reference-data-api.html">Ripple Data API v2</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorials <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="tutorial-multisign.html">How to Multi-Sign</a></li>
|
||||
<li><a href="tutorial-paychan.html">Payment Channels Tutorial</a></li>
|
||||
<li><a href="concept-issuing-and-operational-addresses.html">Issuing and Operational Addresses</a></li>
|
||||
<li><a href="tutorial-reliable-transaction-submission.html">Reliable Transaction Submission</a></li>
|
||||
<li><a href="tutorial-rippleapi-beginners-guide.html">RippleAPI Beginners Guide</a></li>
|
||||
<li><a href="tutorial-rippled-setup.html">rippled Setup</a></li>
|
||||
<li><a href="tutorial-gateway-guide.html">Gateway Guide</a></li>
|
||||
<li><a href="tutorial-listing-xrp.html">Listing XRP as an Exchange</a></li>
|
||||
<li><a href="tutorial-escrow.html">Escrow Tutorials</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Features <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="concept-accounts.html">Accounts</a></li>
|
||||
<li><a href="concept-amendments.html">Amendments</a></li>
|
||||
<li><a href="concept-consensus.html">Consensus Process</a></li>
|
||||
<li><a href="concept-reaching-consensus.html">Reaching Consensus in the XRP Ledger</a></li>
|
||||
<li><a href="concept-fee-voting.html">Fee Voting</a></li>
|
||||
<li><a href="concept-fees.html">Fees (Disambiguation)</a></li>
|
||||
<li><a href="concept-freeze.html">Freeze</a></li>
|
||||
<li><a href="concept-partial-payments.html">Partial Payments</a></li>
|
||||
<li><a href="concept-paths.html">Paths</a></li>
|
||||
<li><a href="concept-reserves.html">Reserves</a></li>
|
||||
<li><a href="concept-stand-alone-mode.html">Stand-Alone Mode</a></li>
|
||||
<li><a href="concept-transaction-cost.html">Transaction Cost</a></li>
|
||||
<li><a href="concept-transfer-fees.html">Transfer Fees</a></li>
|
||||
<li><a href="concept-noripple.html">Understanding the NoRipple flag</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Gateway Bulletins <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="gb-2015-06.html">GB-2015-06: Corrections to Autobridging</a></li>
|
||||
<li><a href="gb-2015-05.html">GB-2015-05: Historical Ledger Query Migration</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">API Tools <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="ripple-api-tool.html">WebSocket API Tool</a></li>
|
||||
<li><a href="data-api-v2-tool.html">Data API v2 Tool</a></li>
|
||||
<li><a href="tool-jsonrpc.html">rippled JSON-RPC Tool</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li><a href="https://github.com/ripple/ripple-dev-portal" title="GitHub">Site Source</a></li>
|
||||
</ul><!-- /#dev-menu -->
|
||||
</div><!-- /.subnav .container -->
|
||||
</div><!-- /.subnav -->
|
||||
</header>
|
||||
|
||||
|
||||
<div class="wrap container" role="document">
|
||||
<aside class="sidebar" role="complementary">
|
||||
<div class="dev_nav_wrapper">
|
||||
<div id="cont">
|
||||
<h5>In this category:</h5>
|
||||
<ul class="dev_nav_sidebar">
|
||||
<li class="level-1"><a href="index.html">Category: Tutorials</a></li>
|
||||
<li class="level-2"><a href="tutorial-multisign.html">How to Multi-Sign</a></li>
|
||||
<li class="level-2"><a href="tutorial-paychan.html">Payment Channels Tutorial</a></li>
|
||||
<li class="level-2"><a href="concept-issuing-and-operational-addresses.html">Issuing and Operational Addresses</a></li>
|
||||
<li class="level-2"><a href="tutorial-reliable-transaction-submission.html">Reliable Transaction Submission</a></li>
|
||||
<li class="level-2"><a href="tutorial-rippleapi-beginners-guide.html">RippleAPI Beginners Guide</a></li>
|
||||
<li class="level-2"><a href="tutorial-rippled-setup.html">rippled Setup</a></li>
|
||||
<li class="level-2"><a href="tutorial-gateway-guide.html">Gateway Guide</a></li>
|
||||
<li class="level-2"><a href="tutorial-listing-xrp.html">Listing XRP as an Exchange</a></li>
|
||||
<li class="level-2"><a href="tutorial-escrow.html">Escrow Tutorials</a></li>
|
||||
</ul>
|
||||
<hr />
|
||||
<h5>In this page:</h5>
|
||||
<ul class="dev_nav_sidebar" id="dactyl_toc_sidebar">
|
||||
<li class="level-1"><a href="#escrow-tutorials">Escrow Tutorials</a></li>
|
||||
<li class="level-2"><a href="#availability-of-escrow">Availability of Escrow</a></li>
|
||||
<li class="level-2"><a href="#send-a-time-held-escrow">Send a Time-Held Escrow</a></li>
|
||||
<li class="level-3"><a href="#1-calculate-release-time">1. Calculate release time</a></li>
|
||||
<li class="level-3"><a href="#2-submit-escrowcreate-transaction">2. Submit EscrowCreate transaction</a></li>
|
||||
<li class="level-3"><a href="#3-wait-for-validation">3. Wait for validation</a></li>
|
||||
<li class="level-3"><a href="#4-confirm-that-the-escrow-was-created">4. Confirm that the escrow was created</a></li>
|
||||
<li class="level-3"><a href="#5-wait-for-the-release-time">5. Wait for the release time</a></li>
|
||||
<li class="level-3"><a href="#6-submit-escrowfinish-transaction">6. Submit EscrowFinish transaction</a></li>
|
||||
<li class="level-3"><a href="#7-wait-for-validation">7. Wait for validation</a></li>
|
||||
<li class="level-3"><a href="#8-confirm-final-result">8. Confirm final result</a></li>
|
||||
<li class="level-2"><a href="#send-a-conditionally-held-escrow">Send a conditionally-held escrow</a></li>
|
||||
<li class="level-3"><a href="#1-generate-condition-and-fulfillment">1. Generate condition and fulfillment</a></li>
|
||||
<li class="level-3"><a href="#2-calculate-release-or-cancel-time">2. Calculate release or cancel time</a></li>
|
||||
<li class="level-3"><a href="#3-submit-escrowcreate-transaction">3. Submit EscrowCreate transaction</a></li>
|
||||
<li class="level-3"><a href="#4-wait-for-validation">4. Wait for validation</a></li>
|
||||
<li class="level-3"><a href="#5-confirm-that-the-escrow-was-created">5. Confirm that the escrow was created</a></li>
|
||||
<li class="level-3"><a href="#6-submit-escrowfinish-transaction-1">6. Submit EscrowFinish transaction</a></li>
|
||||
<li class="level-3"><a href="#7-wait-for-validation-1">7. Wait for validation</a></li>
|
||||
<li class="level-3"><a href="#8-confirm-final-result-1">8. Confirm final result</a></li>
|
||||
<li class="level-2"><a href="#look-up-escrows-by-sender">Look up escrows by sender</a></li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
<main class="main" role="main">
|
||||
<div class='content'>
|
||||
<h1 id="escrow-tutorials">Escrow Tutorials</h1>
|
||||
<p>The XRP Ledger supports held payments, or <em>escrows</em>, that can be executed only after a certain time has passed or a cryptographic condition has been fulfilled. Escrows can only send XRP, not issued currencies. You can use these features to build publicly-provable smart contracts. This article explains basic tasks relating to held payments.</p>
|
||||
<ul>
|
||||
<li><a href="#send-a-time-held-escrow">Send a time-held escrow</a></li>
|
||||
<li><a href="#send-a-conditionally-held-escrow">Send a conditionally-held escrow</a></li>
|
||||
<li><a href="#look-up-escrows-by-sender">Look up escrows by sender</a>
|
||||
<!-- --></li>
|
||||
</ul>
|
||||
<h2 id="availability-of-escrow">Availability of Escrow</h2>
|
||||
<p>Held payments been enabled by the <a href="concept-amendments.html#escrow">"Escrow" Amendment</a> to the XRP Ledger Consensus Protocol since 2017-03-31. A previous version of the same functionality was available on the <a href="https://ripple.com/build/ripple-test-net/">Ripple Test Net</a> by the name "Suspended Payments" (SusPay) in 2016.</p>
|
||||
<p>When testing in <a href="concept-stand-alone-mode.html">stand-alone mode</a>, you can force the Escrow feature to be enabled locally regardless of the amendment status. Add the following stanza to your <code>rippled.cfg</code>:</p>
|
||||
<pre><code>[features]
|
||||
Escrow
|
||||
</code></pre>
|
||||
<p>You can check the status of the Escrow amendment using the <a href="reference-rippled.html#feature"><code>feature</code> command</a>.</p>
|
||||
<h2 id="send-a-time-held-escrow">Send a Time-Held Escrow</h2>
|
||||
<p>The <a href="reference-transaction-format.html#escrowcreate">EscrowCreate transaction</a> type can create an escrow whose only condition for release is that a specific time has passed. To do this, use the <code>FinishAfter</code> field and omit the <code>Condition</code> field.</p>
|
||||
<h3 id="1-calculate-release-time">1. Calculate release time</h3>
|
||||
<p>You must <a href="reference-rippled.html#specifying-time">specify the time</a> as whole <strong>seconds since the Ripple Epoch</strong>, which is 946684800 seconds after the UNIX epoch. For example, to release funds at midnight UTC on November 13, 2017:</p>
|
||||
<div class="multicode" id="code-0"><ul class="codetabs"><li><a href="#code-0-0">JavaScript</a></li></ul>
|
||||
|
||||
<div class="code_sample" id="code-0-0" style="position: static;"><pre><code class="js">// JavaScript Date() is natively expressed in milliseconds; convert to seconds
|
||||
const release_date_unix = Math.floor( new Date("2017-11-13T00:00:00Z") / 1000 );
|
||||
const release_date_ripple = release_date_unix - 946684800;
|
||||
console.log(release_date_ripple);
|
||||
// 563846400
|
||||
</code></pre></div>
|
||||
<!-- -->
|
||||
</div>
|
||||
<p class="devportal-callout warning"><strong>Warning:</strong> If you use a UNIX time in the <code>FinishAfter</code> field without converting to the equivalent Ripple time first, that sets the unlock time to an extra <strong>30 years</strong> in the future!</p>
|
||||
<h3 id="2-submit-escrowcreate-transaction">2. Submit EscrowCreate transaction</h3>
|
||||
<p><a href="reference-transaction-format.html#signing-and-submitting-transactions">Sign and submit</a> an <a href="reference-transaction-format.html#escrowcreate">EscrowCreate transaction</a>. Set the <code>FinishAfter</code> field of the transaction to the time when the held payment should be released. Omit the <code>Condition</code> field to make time the only condition for releasing the held payment. Set the <code>Destination</code> to the recipient, which may be the same address as the sender.</p>
|
||||
<p class="devportal-callout caution"><strong>Caution:</strong> Never submit a secret key to a server you do not control. Do not send a secret key unencrypted over the network.</p>
|
||||
<p>Request:</p>
|
||||
<div class="multicode" id="code-1"><ul class="codetabs"><li><a href="#code-1-0">Websocket</a></li></ul>
|
||||
|
||||
<div class="code_sample" id="code-1-0" style="position: static;"><pre><code class="json">{
|
||||
"id": 2,
|
||||
"command": "submit",
|
||||
"secret": "s████████████████████████████",
|
||||
"tx_json": {
|
||||
"Account": "rajgkBmMxmz161r8bWYH7CQAFZP5bA9oSG",
|
||||
"TransactionType": "EscrowCreate",
|
||||
"Amount": "10000",
|
||||
"Destination": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"FinishAfter": 557020800
|
||||
}
|
||||
}
|
||||
</code></pre></div>
|
||||
</div>
|
||||
<p>Response:</p>
|
||||
<div class="multicode" id="code-2"><ul class="codetabs"><li><a href="#code-2-0">Websocket</a></li></ul>
|
||||
|
||||
<div class="code_sample" id="code-2-0" style="position: static;"><pre><code class="json">{
|
||||
"id": 2,
|
||||
"status": "success",
|
||||
"type": "response",
|
||||
"result": {
|
||||
"engine_result": "tesSUCCESS",
|
||||
"engine_result_code": 0,
|
||||
"engine_result_message": "The transaction was applied. Only final in a validated ledger.",
|
||||
"tx_blob": "1200012280000000240000000120252133768061400000000000271068400000000000000A732103C3555B7339FFDDB43495A8371A3A87B4C66B67D49D06CB9BA1FDBFEEB57B6E437446304402203C9AA4C21E1A1A7427D41583283E7A513DDBDD967B246CADD3B2705D858A7A8E02201BEA7B923B18910EEB9F306F6DE3B3F53549BBFAD46335B62B4C34A6DCB4A47681143EEB46C355B04EE8D08E8EED00F422895C79EA6A83144B4E9C06F24296074F7BC48F92A97916C6DC5EA9",
|
||||
"tx_json": {
|
||||
"Account": "rajgkBmMxmz161r8bWYH7CQAFZP5bA9oSG",
|
||||
"Amount": "10000",
|
||||
"Destination": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"Fee": "10",
|
||||
"FinishAfter": 557020800,
|
||||
"Flags": 2147483648,
|
||||
"Sequence": 1,
|
||||
"SigningPubKey": "03C3555B7339FFDDB43495A8371A3A87B4C66B67D49D06CB9BA1FDBFEEB57B6E43",
|
||||
"TransactionType": "EscrowCreate",
|
||||
"TxnSignature": "304402203C9AA4C21E1A1A7427D41583283E7A513DDBDD967B246CADD3B2705D858A7A8E02201BEA7B923B18910EEB9F306F6DE3B3F53549BBFAD46335B62B4C34A6DCB4A476",
|
||||
"hash": "55B2057332F8999208C43BA1E7091B423A16E5ED2736C06300B4076085205263"
|
||||
}
|
||||
}
|
||||
}
|
||||
</code></pre></div>
|
||||
</div>
|
||||
<p>Take note of the transaction's identifying <code>hash</code> value so you can check its final status when it is included in a validated ledger version.</p>
|
||||
<h3 id="3-wait-for-validation">3. Wait for validation</h3>
|
||||
<p>On the live network or the Ripple Test Net, you can wait 4-7 seconds for the ledger to close automatically.</p>
|
||||
<p>If you're running <code>rippled</code> in stand-alone mode, use the <a href="reference-rippled.html#ledger-accept"><code>ledger_accept</code> command</a> to manually close the ledger.</p>
|
||||
<h3 id="4-confirm-that-the-escrow-was-created">4. Confirm that the escrow was created</h3>
|
||||
<p>Use the <a href="reference-rippled.html#tx"><code>tx</code> command</a> with the transaction's identifying hash to check its final status. Look for a <code>CreatedNode</code> in the transaction metadata to indicate that it created an <a href="reference-ledger-format.html#escrow">Escrow ledger object</a>.</p>
|
||||
<p>Request:</p>
|
||||
<div class="multicode" id="code-3"><ul class="codetabs"><li><a href="#code-3-0">Websocket</a></li></ul>
|
||||
|
||||
<div class="code_sample" id="code-3-0" style="position: static;"><pre><code class="json">{
|
||||
"id": 3,
|
||||
"command": "tx",
|
||||
"transaction": "55B2057332F8999208C43BA1E7091B423A16E5ED2736C06300B4076085205263"
|
||||
}
|
||||
</code></pre></div>
|
||||
</div>
|
||||
<p>Response:</p>
|
||||
<div class="multicode" id="code-4"><ul class="codetabs"><li><a href="#code-4-0">Websocket</a></li></ul>
|
||||
|
||||
<div class="code_sample" id="code-4-0" style="position: static;"><pre><code class="json">{
|
||||
"id": 3,
|
||||
"status": "success",
|
||||
"type": "response",
|
||||
"result": {
|
||||
"Account": "rajgkBmMxmz161r8bWYH7CQAFZP5bA9oSG",
|
||||
"Amount": "10000",
|
||||
"Destination": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"Fee": "10",
|
||||
"FinishAfter": 557020800,
|
||||
"Flags": 2147483648,
|
||||
"Sequence": 1,
|
||||
"SigningPubKey": "03C3555B7339FFDDB43495A8371A3A87B4C66B67D49D06CB9BA1FDBFEEB57B6E43",
|
||||
"TransactionType": "EscrowCreate",
|
||||
"TxnSignature": "304402203C9AA4C21E1A1A7427D41583283E7A513DDBDD967B246CADD3B2705D858A7A8E02201BEA7B923B18910EEB9F306F6DE3B3F53549BBFAD46335B62B4C34A6DCB4A476",
|
||||
"date": 557014081,
|
||||
"hash": "55B2057332F8999208C43BA1E7091B423A16E5ED2736C06300B4076085205263",
|
||||
"inLedger": 1828796,
|
||||
"ledger_index": 1828796,
|
||||
"meta": {
|
||||
"AffectedNodes": [
|
||||
{
|
||||
"ModifiedNode": {
|
||||
"LedgerEntryType": "AccountRoot",
|
||||
"LedgerIndex": "13F1A95D7AAB7108D5CE7EEAF504B2894B8C674E6D68499076441C4837282BF8",
|
||||
"PreviousTxnID": "613B28E0890FC975F2CBA3D700F75116F623B1E3FE48CB7CB2EB216EAD6F097D",
|
||||
"PreviousTxnLgrSeq": 1799920
|
||||
}
|
||||
},
|
||||
{
|
||||
"CreatedNode": {
|
||||
"LedgerEntryType": "Escrow",
|
||||
"LedgerIndex": "2B9845CB9DF686B9615BF04F3EC66095A334D985E03E71B893B90FCF6D4DC9E6",
|
||||
"NewFields": {
|
||||
"Account": "rajgkBmMxmz161r8bWYH7CQAFZP5bA9oSG",
|
||||
"Amount": "10000",
|
||||
"Destination": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"FinishAfter": 557020800
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"ModifiedNode": {
|
||||
"FinalFields": {
|
||||
"Account": "rajgkBmMxmz161r8bWYH7CQAFZP5bA9oSG",
|
||||
"Balance": "9999989990",
|
||||
"Flags": 0,
|
||||
"OwnerCount": 1,
|
||||
"Sequence": 2
|
||||
},
|
||||
"LedgerEntryType": "AccountRoot",
|
||||
"LedgerIndex": "AE5AB6584A76C37C7382B6880609FC7792D90CDA36FF362AF412EB914C1715D3",
|
||||
"PreviousFields": {
|
||||
"Balance": "10000000000",
|
||||
"OwnerCount": 0,
|
||||
"Sequence": 1
|
||||
},
|
||||
"PreviousTxnID": "F181D45FD094A7417926F791D9DF958B84CE4B7B3D92CC9DDCACB1D5EC59AAAA",
|
||||
"PreviousTxnLgrSeq": 1828732
|
||||
}
|
||||
},
|
||||
{
|
||||
"CreatedNode": {
|
||||
"LedgerEntryType": "DirectoryNode",
|
||||
"LedgerIndex": "D623EBEEEE701D4323D0ADA5320AF35EA8CC6520EBBEF69343354CD593DABC88",
|
||||
"NewFields": {
|
||||
"Owner": "rajgkBmMxmz161r8bWYH7CQAFZP5bA9oSG",
|
||||
"RootIndex": "D623EBEEEE701D4323D0ADA5320AF35EA8CC6520EBBEF69343354CD593DABC88"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"TransactionIndex": 3,
|
||||
"TransactionResult": "tesSUCCESS"
|
||||
},
|
||||
"validated": true
|
||||
}
|
||||
}
|
||||
</code></pre></div>
|
||||
</div>
|
||||
<h3 id="5-wait-for-the-release-time">5. Wait for the release time</h3>
|
||||
<p>Held payments with a <code>FinishAfter</code> time cannot be finished until a ledger has already closed with a <a href="reference-ledger-format.html#header-format"><code>close_time</code> header field</a> that is later than the Escrow node's <code>FinishAfter</code> time.</p>
|
||||
<p>You can check the close time of the most recently-validated ledger with the <a href="reference-rippled.html#ledger"><code>ledger</code> command</a>:</p>
|
||||
<p>Request:</p>
|
||||
<div class="multicode" id="code-5"><ul class="codetabs"><li><a href="#code-5-0">Websocket</a></li></ul>
|
||||
|
||||
<div class="code_sample" id="code-5-0" style="position: static;"><pre><code class="json">{
|
||||
"id": 4,
|
||||
"command": "ledger",
|
||||
"ledger_index": "validated"
|
||||
}
|
||||
</code></pre></div>
|
||||
</div>
|
||||
<p>Response:</p>
|
||||
<div class="multicode" id="code-6"><ul class="codetabs"><li><a href="#code-6-0">Websocket</a></li></ul>
|
||||
|
||||
<div class="code_sample" id="code-6-0" style="position: static;"><pre><code class="json">{
|
||||
"id": 4,
|
||||
"status": "success",
|
||||
"type": "response",
|
||||
"result": {
|
||||
"ledger": {
|
||||
"accepted": true,
|
||||
"account_hash": "3B5A8FF5334F94F4D3D09F236F9D1B4C028FCAE30948ACC986D461DDEE1D886B",
|
||||
"close_flags": 0,
|
||||
"close_time": 557256670,
|
||||
"close_time_human": "2017-Aug-28 17:31:10",
|
||||
"close_time_resolution": 10,
|
||||
"closed": true,
|
||||
"hash": "A999223A80174A7CB39D766B625C9E476F24AD2F15860A712CD029EE5ED1C320",
|
||||
"ledger_hash": "A999223A80174A7CB39D766B625C9E476F24AD2F15860A712CD029EE5ED1C320",
|
||||
"ledger_index": "1908253",
|
||||
"parent_close_time": 557256663,
|
||||
"parent_hash": "6A70C5336ACFDA05760D827776079F7A544D2361CFD5B21BD55A92AA20477A61",
|
||||
"seqNum": "1908253",
|
||||
"totalCoins": "99997280690562728",
|
||||
"total_coins": "99997280690562728",
|
||||
"transaction_hash": "49A51DFB1CAB2F134D93D5D1C5FF55A15B12DA36DAF9F5862B17C47EE966647D"
|
||||
},
|
||||
"ledger_hash": "A999223A80174A7CB39D766B625C9E476F24AD2F15860A712CD029EE5ED1C320",
|
||||
"ledger_index": 1908253,
|
||||
"validated": true
|
||||
}
|
||||
}
|
||||
</code></pre></div>
|
||||
</div>
|
||||
<h3 id="6-submit-escrowfinish-transaction">6. Submit EscrowFinish transaction</h3>
|
||||
<p><a href="reference-transaction-format.html#signing-and-submitting-transactions">Sign and submit</a> an <a href="reference-transaction-format.html#escrowfinish">EscrowFinish transaction</a> to execute the release of the funds after the <code>FinishAfter</code> time has passed. Set the <code>Owner</code> field of the transaction to the <code>Account</code> address from the EscrowCreate transaction, and the <code>OfferSequence</code> to the <code>Sequence</code> number from the EscrowCreate transaction. For an escrow held only by time, omit the <code>Condition</code> and <code>Fulfillment</code> fields.</p>
|
||||
<p class="devportal-callout tip"><strong>Tip:</strong> The EscrowFinish transaction is necessary because the XRP Ledger's state can only be modified by transactions. The sender of this transaction may be the recipient of the escrow, the original sender of the escrow, or any other XRP Ledger address.</p>
|
||||
<p class="devportal-callout caution"><strong>Caution:</strong> Never submit a secret key to a server you do not control. Do not send a secret key unencrypted over the network.</p>
|
||||
<p>Request:</p>
|
||||
<div class="multicode" id="code-7"><ul class="codetabs"><li><a href="#code-7-0">Websocket</a></li></ul>
|
||||
|
||||
<div class="code_sample" id="code-7-0" style="position: static;"><pre><code class="json">{
|
||||
"id": 5,
|
||||
"command": "submit",
|
||||
"secret": "s████████████████████████████",
|
||||
"tx_json": {
|
||||
"Account": "rajgkBmMxmz161r8bWYH7CQAFZP5bA9oSG",
|
||||
"TransactionType": "EscrowFinish",
|
||||
"Owner": "rajgkBmMxmz161r8bWYH7CQAFZP5bA9oSG",
|
||||
"OfferSequence": 1
|
||||
}
|
||||
}
|
||||
</code></pre></div>
|
||||
</div>
|
||||
<p>Response:</p>
|
||||
<div class="multicode" id="code-8"><ul class="codetabs"><li><a href="#code-8-0">Websocket</a></li></ul>
|
||||
|
||||
<div class="code_sample" id="code-8-0" style="position: static;"><pre><code class="json">{
|
||||
"id": 5,
|
||||
"status": "success",
|
||||
"type": "response",
|
||||
"result": {
|
||||
"engine_result": "tesSUCCESS",
|
||||
"engine_result_code": 0,
|
||||
"engine_result_message": "The transaction was applied. Only final in a validated ledger.",
|
||||
"tx_blob": "1200022280000000240000000220190000000168400000000000000A732103C3555B7339FFDDB43495A8371A3A87B4C66B67D49D06CB9BA1FDBFEEB57B6E4374473045022100923B91BA4FD6450813F5335D71C64BA9EB81304A86859A631F2AD8571424A46502200CCE660D36781B84634C5F23619EB6CFCCF942709F54DCCF27CF6F499AE78C9B81143EEB46C355B04EE8D08E8EED00F422895C79EA6A82143EEB46C355B04EE8D08E8EED00F422895C79EA6A",
|
||||
"tx_json": {
|
||||
"Account": "rajgkBmMxmz161r8bWYH7CQAFZP5bA9oSG",
|
||||
"Fee": "10",
|
||||
"Flags": 2147483648,
|
||||
"OfferSequence": 1,
|
||||
"Owner": "rajgkBmMxmz161r8bWYH7CQAFZP5bA9oSG",
|
||||
"Sequence": 2,
|
||||
"SigningPubKey": "03C3555B7339FFDDB43495A8371A3A87B4C66B67D49D06CB9BA1FDBFEEB57B6E43",
|
||||
"TransactionType": "EscrowFinish",
|
||||
"TxnSignature": "3045022100923B91BA4FD6450813F5335D71C64BA9EB81304A86859A631F2AD8571424A46502200CCE660D36781B84634C5F23619EB6CFCCF942709F54DCCF27CF6F499AE78C9B",
|
||||
"hash": "41856A742B3CAF307E7B4D0B850F302101F0F415B785454F7501E9960A2A1F6B"
|
||||
}
|
||||
}
|
||||
}
|
||||
</code></pre></div>
|
||||
</div>
|
||||
<p>Take note of the transaction's identifying <code>hash</code> value so you can check its final status when it is included in a validated ledger version.</p>
|
||||
<h3 id="7-wait-for-validation">7. Wait for validation</h3>
|
||||
<p>On the live network or the Ripple Test Net, you can wait 4-7 seconds for the ledger to close automatically.</p>
|
||||
<p>If you're running <code>rippled</code> in stand-alone mode, use the <a href="reference-rippled.html#ledger-accept"><code>ledger_accept</code> command</a> to manually close the ledger.</p>
|
||||
<h3 id="8-confirm-final-result">8. Confirm final result</h3>
|
||||
<p>Use the <a href="reference-rippled.html#tx"><code>tx</code> command</a> with the EscrowFinish transaction's identifying hash to check its final status. In particular, look in the transaction metadata for a <code>ModifiedNode</code> of type <code>AccountRoot</code> for the destination of the escrowed payment. The <code>FinalFields</code> of the object should reflect the increase in XRP in the <code>Balance</code> field.</p>
|
||||
<p>Request:</p>
|
||||
<div class="multicode" id="code-9"><ul class="codetabs"><li><a href="#code-9-0">Websocket</a></li></ul>
|
||||
|
||||
<div class="code_sample" id="code-9-0" style="position: static;"><pre><code class="json">{
|
||||
"id": 21,
|
||||
"command": "tx",
|
||||
"transaction": "41856A742B3CAF307E7B4D0B850F302101F0F415B785454F7501E9960A2A1F6B"
|
||||
}
|
||||
</code></pre></div>
|
||||
</div>
|
||||
<p>Response:</p>
|
||||
<div class="multicode" id="code-10"><ul class="codetabs"><li><a href="#code-10-0">Websocket</a></li></ul>
|
||||
|
||||
<div class="code_sample" id="code-10-0" style="position: static;"><pre><code class="json">{
|
||||
"id": 21,
|
||||
"status": "success",
|
||||
"type": "response",
|
||||
"result": {
|
||||
"Account": "rajgkBmMxmz161r8bWYH7CQAFZP5bA9oSG",
|
||||
"Fee": "10",
|
||||
"Flags": 2147483648,
|
||||
"OfferSequence": 1,
|
||||
"Owner": "rajgkBmMxmz161r8bWYH7CQAFZP5bA9oSG",
|
||||
"Sequence": 2,
|
||||
"SigningPubKey": "03C3555B7339FFDDB43495A8371A3A87B4C66B67D49D06CB9BA1FDBFEEB57B6E43",
|
||||
"TransactionType": "EscrowFinish",
|
||||
"TxnSignature": "3045022100923B91BA4FD6450813F5335D71C64BA9EB81304A86859A631F2AD8571424A46502200CCE660D36781B84634C5F23619EB6CFCCF942709F54DCCF27CF6F499AE78C9B",
|
||||
"date": 557256681,
|
||||
"hash": "41856A742B3CAF307E7B4D0B850F302101F0F415B785454F7501E9960A2A1F6B",
|
||||
"inLedger": 1908257,
|
||||
"ledger_index": 1908257,
|
||||
"meta": {
|
||||
"AffectedNodes": [
|
||||
{
|
||||
"ModifiedNode": {
|
||||
"FinalFields": {
|
||||
"Account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"Balance": "400210000",
|
||||
"Flags": 0,
|
||||
"OwnerCount": 0,
|
||||
"Sequence": 1
|
||||
},
|
||||
"LedgerEntryType": "AccountRoot",
|
||||
"LedgerIndex": "13F1A95D7AAB7108D5CE7EEAF504B2894B8C674E6D68499076441C4837282BF8",
|
||||
"PreviousFields": {
|
||||
"Balance": "400200000"
|
||||
},
|
||||
"PreviousTxnID": "55B2057332F8999208C43BA1E7091B423A16E5ED2736C06300B4076085205263",
|
||||
"PreviousTxnLgrSeq": 1828796
|
||||
}
|
||||
},
|
||||
{
|
||||
"DeletedNode": {
|
||||
"FinalFields": {
|
||||
"Account": "rajgkBmMxmz161r8bWYH7CQAFZP5bA9oSG",
|
||||
"Amount": "10000",
|
||||
"Destination": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"FinishAfter": 557020800,
|
||||
"Flags": 0,
|
||||
"OwnerNode": "0000000000000000",
|
||||
"PreviousTxnID": "55B2057332F8999208C43BA1E7091B423A16E5ED2736C06300B4076085205263",
|
||||
"PreviousTxnLgrSeq": 1828796
|
||||
},
|
||||
"LedgerEntryType": "Escrow",
|
||||
"LedgerIndex": "2B9845CB9DF686B9615BF04F3EC66095A334D985E03E71B893B90FCF6D4DC9E6"
|
||||
}
|
||||
},
|
||||
{
|
||||
"ModifiedNode": {
|
||||
"FinalFields": {
|
||||
"Account": "rajgkBmMxmz161r8bWYH7CQAFZP5bA9oSG",
|
||||
"Balance": "9999989980",
|
||||
"Flags": 0,
|
||||
"OwnerCount": 0,
|
||||
"Sequence": 3
|
||||
},
|
||||
"LedgerEntryType": "AccountRoot",
|
||||
"LedgerIndex": "AE5AB6584A76C37C7382B6880609FC7792D90CDA36FF362AF412EB914C1715D3",
|
||||
"PreviousFields": {
|
||||
"Balance": "9999989990",
|
||||
"OwnerCount": 1,
|
||||
"Sequence": 2
|
||||
},
|
||||
"PreviousTxnID": "55B2057332F8999208C43BA1E7091B423A16E5ED2736C06300B4076085205263",
|
||||
"PreviousTxnLgrSeq": 1828796
|
||||
}
|
||||
},
|
||||
{
|
||||
"ModifiedNode": {
|
||||
"FinalFields": {
|
||||
"Flags": 0,
|
||||
"Owner": "rajgkBmMxmz161r8bWYH7CQAFZP5bA9oSG",
|
||||
"RootIndex": "D623EBEEEE701D4323D0ADA5320AF35EA8CC6520EBBEF69343354CD593DABC88"
|
||||
},
|
||||
"LedgerEntryType": "DirectoryNode",
|
||||
"LedgerIndex": "D623EBEEEE701D4323D0ADA5320AF35EA8CC6520EBBEF69343354CD593DABC88"
|
||||
}
|
||||
}
|
||||
],
|
||||
"TransactionIndex": 2,
|
||||
"TransactionResult": "tesSUCCESS"
|
||||
},
|
||||
"validated": true
|
||||
}
|
||||
}
|
||||
</code></pre></div>
|
||||
</div>
|
||||
<h2 id="send-a-conditionally-held-escrow">Send a conditionally-held escrow</h2>
|
||||
<h3 id="1-generate-condition-and-fulfillment">1. Generate condition and fulfillment</h3>
|
||||
<p>XRP Ledger escrows require PREIMAGE-SHA-256 <a href="https://tools.ietf.org/html/draft-thomas-crypto-conditions-03">Crypto-Conditions</a>. To calculate a condition and fulfillment in the proper format, you should use a Crypto-Conditions library such as <a href="https://github.com/interledgerjs/five-bells-condition">five-bells-condition</a>. For fulfillments, Ripple recommends using one of the following methods to generate the fulfillment:</p>
|
||||
<ul>
|
||||
<li>Use a cryptographically secure source of randomness to generate at least 32 random bytes.</li>
|
||||
<li>Follow Interledger Protocol's <a href="https://github.com/interledger/rfcs/blob/master/0016-pre-shared-key/0016-pre-shared-key.md">PSK specification</a> and use an HMAC-SHA-256 of the ILP packet as the fulfillment.</li>
|
||||
</ul>
|
||||
<p>Example JavaScript code for a random fulfillment and condition:</p>
|
||||
<pre><code class="js">cc = require('five-bells-condition');
|
||||
|
||||
const fulfillment_bytes = crypto.randomBytes(32);
|
||||
const myFulfillment = new cc.PreimageSha256();
|
||||
myFulfillment.setPreimage(fulfillment_bytes);
|
||||
console.log(myFulfillment.serializeBinary().toString('hex'));
|
||||
// (Random hexadecimal, 72 chars in length)
|
||||
console.log(myFulfillment.getConditionBinary().toString('hex'));
|
||||
// (Random hexadecimal, 78 chars in length)
|
||||
</code></pre>
|
||||
<p>Save the condition and the fulfillment for later. Be sure to keep the fulfillment secret until you want to finish executing the held payment. Anyone who knows the fulfillment can finish the escrow, releasing the held funds to their intended destination.</p>
|
||||
<h3 id="2-calculate-release-or-cancel-time">2. Calculate release or cancel time</h3>
|
||||
<p>A Conditional <code>Escrow</code> transaction must contain either a <code>CancelAfter</code> or <code>FinishAfter</code> field, or both. The <code>CancelAfter</code> field lets the XRP revert to the sender if the condition is not fulfilled before the specified time. The <code>FinishAfter</code> field specifies a time before which the escrow cannot execute, even if someone sends the correct fulfillment. Whichever field you provide, the time it specifies must be in the future.</p>
|
||||
<p>Example for setting a <code>CancelAfter</code> time of 24 hours in the future:</p>
|
||||
<div class="multicode" id="code-11"><ul class="codetabs"><li><a href="#code-11-0">JavaScript</a></li></ul>
|
||||
|
||||
<div class="code_sample" id="code-11-0" style="position: static;"><pre><code class="js">const rippleOffset = 946684800;
|
||||
const CancelAfter = Math.floor(Date.now() / 1000) + (24*60*60) - rippleOffset;
|
||||
console.log(CancelAfter);
|
||||
// Example: 556927412
|
||||
</code></pre></div>
|
||||
<!-- -->
|
||||
</div>
|
||||
<p class="devportal-callout warning"><strong>Warning:</strong> In the XRP Ledger, you must specify time as <strong>seconds since the Ripple Epoch</strong> (2000-01-01T00:00:00Z). If you use a UNIX time in the <code>CancelAfter</code> or <code>FinishAfter</code> field without converting to the equivalent Ripple time first, that sets the unlock time to an extra <strong>30 years</strong> in the future!</p>
|
||||
<h3 id="3-submit-escrowcreate-transaction">3. Submit EscrowCreate transaction</h3>
|
||||
<p><a href="reference-transaction-format.html#signing-and-submitting-transactions">Sign and submit</a> an <a href="reference-transaction-format.html#escrowcreate">EscrowCreate transaction</a>. Set the <code>Condition</code> field of the transaction to the time when the held payment should be released. Set the <code>Destination</code> to the recipient, which can be the same address as the sender. Include the <code>CancelAfter</code> or <code>FinishAfter</code> time you calculated in the previous step.</p>
|
||||
<p class="devportal-callout caution"><strong>Caution:</strong> Never submit a secret key to a server you do not control. Do not send a secret key unencrypted over the network.</p>
|
||||
<p>Request:</p>
|
||||
<div class="multicode" id="code-12"><ul class="codetabs"><li><a href="#code-12-0">Websocket</a></li></ul>
|
||||
|
||||
<div class="code_sample" id="code-12-0" style="position: static;"><pre><code class="json">{
|
||||
"id": 1,
|
||||
"command": "submit",
|
||||
"secret": "s████████████████████████████",
|
||||
"tx_json": {
|
||||
"Account": "rEhw9vD98ZrkY4tZPvkZst5H18RysqFdaB",
|
||||
"TransactionType": "EscrowCreate",
|
||||
"Amount": "100000",
|
||||
"Destination": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"Condition": "A0258020E24D9E1473D4DF774F6D8E089067282034E4FA7ECACA2AD2E547953B2C113CBD810120",
|
||||
"CancelAfter": 556927412
|
||||
}
|
||||
}
|
||||
</code></pre></div>
|
||||
</div>
|
||||
<p>Response:</p>
|
||||
<div class="multicode" id="code-13"><ul class="codetabs"><li><a href="#code-13-0">Websocket</a></li></ul>
|
||||
|
||||
<div class="code_sample" id="code-13-0" style="position: static;"><pre><code class="json">{
|
||||
"id": 1,
|
||||
"status": "success",
|
||||
"type": "response",
|
||||
"result": {
|
||||
"engine_result": "tesSUCCESS",
|
||||
"engine_result_code": 0,
|
||||
"engine_result_message": "The transaction was applied. Only final in a validated ledger.",
|
||||
"tx_blob": "120001228000000024000000052024213209B46140000000000186A068400000000000000A732103E498E35BC1E109C5995BD3AB0A6D4FFAB61B853C8F6010FABC5DABAF34478B61744730450221008AC8BDC2151D5EF956197F0E6E89A4F49DEADC1AC38367870E444B1EA8D88D97022075E31427B455DFF87F0F22B849C71FC3987A91C19D63B6D0242E808347EC8A8F701127A0258020E24D9E1473D4DF774F6D8E089067282034E4FA7ECACA2AD2E547953B2C113CBD81012081149A2AA667E1517EFA8A6B552AB2EDB859A99F26B283144B4E9C06F24296074F7BC48F92A97916C6DC5EA9",
|
||||
"tx_json": {
|
||||
"Account": "rEhw9vD98ZrkY4tZPvkZst5H18RysqFdaB",
|
||||
"Amount": "100000",
|
||||
"CancelAfter": 556927412,
|
||||
"Condition": "A0258020E24D9E1473D4DF774F6D8E089067282034E4FA7ECACA2AD2E547953B2C113CBD810120",
|
||||
"Destination": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"Fee": "10",
|
||||
"Flags": 2147483648,
|
||||
"Sequence": 5,
|
||||
"SigningPubKey": "03E498E35BC1E109C5995BD3AB0A6D4FFAB61B853C8F6010FABC5DABAF34478B61",
|
||||
"TransactionType": "EscrowCreate",
|
||||
"TxnSignature": "30450221008AC8BDC2151D5EF956197F0E6E89A4F49DEADC1AC38367870E444B1EA8D88D97022075E31427B455DFF87F0F22B849C71FC3987A91C19D63B6D0242E808347EC8A8F",
|
||||
"hash": "E22D1F6EB006CAD35E0DBD3B4F3748427055E4C143EBE95AA6603823AEEAD324"
|
||||
}
|
||||
}
|
||||
}
|
||||
</code></pre></div>
|
||||
</div>
|
||||
<h3 id="4-wait-for-validation">4. Wait for validation</h3>
|
||||
<p>On the live network or the Ripple Test Net, you can wait 4-7 seconds for the ledger to close automatically.</p>
|
||||
<p>If you're running <code>rippled</code> in stand-alone mode, use the <a href="reference-rippled.html#ledger-accept"><code>ledger_accept</code> command</a> to manually close the ledger.</p>
|
||||
<h3 id="5-confirm-that-the-escrow-was-created">5. Confirm that the escrow was created</h3>
|
||||
<p>Use the <a href="reference-rippled.html#tx"><code>tx</code> command</a> with the transaction's identifying hash to check its final status. In particular, look for a <code>CreatedNode</code> in the transaction metadata to indicate that it created an <a href="reference-ledger-format.html#escrow">Escrow ledger object</a>.</p>
|
||||
<p>Request:</p>
|
||||
<div class="multicode" id="code-14"><ul class="codetabs"><li><a href="#code-14-0">Websocket</a></li></ul>
|
||||
|
||||
<div class="code_sample" id="code-14-0" style="position: static;"><pre><code class="json">{
|
||||
"id": 3,
|
||||
"command": "tx",
|
||||
"transaction": "E22D1F6EB006CAD35E0DBD3B4F3748427055E4C143EBE95AA6603823AEEAD324"
|
||||
}
|
||||
</code></pre></div>
|
||||
</div>
|
||||
<p>Response:</p>
|
||||
<div class="multicode" id="code-15"><ul class="codetabs"><li><a href="#code-15-0">Websocket</a></li></ul>
|
||||
|
||||
<div class="code_sample" id="code-15-0" style="position: static;"><pre><code class="json">{
|
||||
"id": 3,
|
||||
"status": "success",
|
||||
"type": "response",
|
||||
"result": {
|
||||
"Account": "rEhw9vD98ZrkY4tZPvkZst5H18RysqFdaB",
|
||||
"Amount": "100000",
|
||||
"CancelAfter": 556927412,
|
||||
"Condition": "A0258020E24D9E1473D4DF774F6D8E089067282034E4FA7ECACA2AD2E547953B2C113CBD810120",
|
||||
"Destination": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"Fee": "10",
|
||||
"Flags": 2147483648,
|
||||
"Sequence": 5,
|
||||
"SigningPubKey": "03E498E35BC1E109C5995BD3AB0A6D4FFAB61B853C8F6010FABC5DABAF34478B61",
|
||||
"TransactionType": "EscrowCreate",
|
||||
"TxnSignature": "30450221008AC8BDC2151D5EF956197F0E6E89A4F49DEADC1AC38367870E444B1EA8D88D97022075E31427B455DFF87F0F22B849C71FC3987A91C19D63B6D0242E808347EC8A8F",
|
||||
"date": 556841101,
|
||||
"hash": "E22D1F6EB006CAD35E0DBD3B4F3748427055E4C143EBE95AA6603823AEEAD324",
|
||||
"inLedger": 1772019,
|
||||
"ledger_index": 1772019,
|
||||
"meta": {
|
||||
"AffectedNodes": [
|
||||
{
|
||||
"ModifiedNode": {
|
||||
"LedgerEntryType": "AccountRoot",
|
||||
"LedgerIndex": "13F1A95D7AAB7108D5CE7EEAF504B2894B8C674E6D68499076441C4837282BF8",
|
||||
"PreviousTxnID": "52C4F626FE6F33699B6BE8ADF362836DDCE9B0B1294BFAA15D65D61501350BE6",
|
||||
"PreviousTxnLgrSeq": 1771204
|
||||
}
|
||||
},
|
||||
{
|
||||
"ModifiedNode": {
|
||||
"FinalFields": {
|
||||
"Flags": 0,
|
||||
"Owner": "rEhw9vD98ZrkY4tZPvkZst5H18RysqFdaB",
|
||||
"RootIndex": "4B4EBB6D8563075813D47491CC325865DFD3DC2E94889F0F39D59D9C059DD81F"
|
||||
},
|
||||
"LedgerEntryType": "DirectoryNode",
|
||||
"LedgerIndex": "4B4EBB6D8563075813D47491CC325865DFD3DC2E94889F0F39D59D9C059DD81F"
|
||||
}
|
||||
},
|
||||
{
|
||||
"ModifiedNode": {
|
||||
"FinalFields": {
|
||||
"Account": "rEhw9vD98ZrkY4tZPvkZst5H18RysqFdaB",
|
||||
"Balance": "9999798970",
|
||||
"Flags": 0,
|
||||
"OwnerCount": 1,
|
||||
"Sequence": 6
|
||||
},
|
||||
"LedgerEntryType": "AccountRoot",
|
||||
"LedgerIndex": "5F3B7107F4B524367A173A2B0EAB66E8CC4D2178C1B0C0528CB2F73A8B6BF254",
|
||||
"PreviousFields": {
|
||||
"Balance": "9999898980",
|
||||
"OwnerCount": 0,
|
||||
"Sequence": 5
|
||||
},
|
||||
"PreviousTxnID": "52C4F626FE6F33699B6BE8ADF362836DDCE9B0B1294BFAA15D65D61501350BE6",
|
||||
"PreviousTxnLgrSeq": 1771204
|
||||
}
|
||||
},
|
||||
{
|
||||
"CreatedNode": {
|
||||
"LedgerEntryType": "Escrow",
|
||||
"LedgerIndex": "E2CF730A31FD419382350C9DBD8DB7CD775BA5AA9B97A9BE9AB07304AA217A75",
|
||||
"NewFields": {
|
||||
"Account": "rEhw9vD98ZrkY4tZPvkZst5H18RysqFdaB",
|
||||
"Amount": "100000",
|
||||
"CancelAfter": 556927412,
|
||||
"Condition": "A0258020E24D9E1473D4DF774F6D8E089067282034E4FA7ECACA2AD2E547953B2C113CBD810120",
|
||||
"Destination": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"TransactionIndex": 0,
|
||||
"TransactionResult": "tesSUCCESS"
|
||||
},
|
||||
"validated": true
|
||||
}
|
||||
}
|
||||
</code></pre></div>
|
||||
</div>
|
||||
<h3 id="6-submit-escrowfinish-transaction-1">6. Submit EscrowFinish transaction</h3>
|
||||
<p><a href="reference-transaction-format.html#signing-and-submitting-transactions">Sign and submit</a> an <a href="reference-transaction-format.html#escrowfinish">EscrowFinish transaction</a> to execute the release of the funds after the <code>FinishAfter</code> time has passed. Set the <code>Owner</code> field of the transaction to the <code>Account</code> address from the EscrowCreate transaction, and the <code>OfferSequence</code> to the <code>Sequence</code> number from the EscrowCreate transaction. Set the <code>Condition</code> and <code>Fulfillment</code> fields to the condition and fulfillment values, in hexadecimal, that you generated in step 1. Set the <code>Fee</code> (<a href="concept-transaction-cost.html">transaction cost</a>) value based on the size of the fulfillment in bytes: a conditional EscrowFinish requires at least 330 drops of XRP plus 10 drops per 16 bytes in the size of the fulfillment.</p>
|
||||
<p class="devportal-callout note"><strong>Note:</strong> If you included a <code>FinishAfter</code> field in the EscrowCreate transaction, you cannot execute it before that time has passed, even if you provide the correct fulfillment for the Escrow's condition. The EscrowFinish transaction fails with the <a href="reference-transaction-format.html#transaction-results">result code</a> <code>tecNO_PERMISSION</code> if the previously-closed ledger's close time is before the <code>FinishAfter</code> time.</p>
|
||||
<p class="devportal-callout caution"><strong>Caution:</strong> Never submit a secret key to a server you do not control. Do not send a secret key unencrypted over the network.</p>
|
||||
<div class="multicode" id="code-16"><ul class="codetabs"><li><a href="#code-16-0">Websocket</a></li></ul>
|
||||
|
||||
<div class="code_sample" id="code-16-0" style="position: static;"><pre><code class="json">{
|
||||
"id": 4,
|
||||
"command": "submit",
|
||||
"secret": "s████████████████████████████",
|
||||
"tx_json": {
|
||||
"Account": "rEhw9vD98ZrkY4tZPvkZst5H18RysqFdaB",
|
||||
"TransactionType": "EscrowFinish",
|
||||
"Owner": "rEhw9vD98ZrkY4tZPvkZst5H18RysqFdaB",
|
||||
"OfferSequence": 5,
|
||||
"Condition": "A0258020E24D9E1473D4DF774F6D8E089067282034E4FA7ECACA2AD2E547953B2C113CBD810120",
|
||||
"Fulfillment": "A0228020D280D1A02BAD0D2EBC0528B92E9BF37AC3E2530832C2C52620307135156F1048",
|
||||
"Fee": "500"
|
||||
}
|
||||
}
|
||||
</code></pre></div>
|
||||
</div>
|
||||
<p>Response:</p>
|
||||
<div class="multicode" id="code-17"><ul class="codetabs"><li><a href="#code-17-0">Websocket</a></li></ul>
|
||||
|
||||
<div class="code_sample" id="code-17-0" style="position: static;"><pre><code class="json">{
|
||||
"id": 4,
|
||||
"status": "success",
|
||||
"type": "response",
|
||||
"result": {
|
||||
"engine_result": "tesSUCCESS",
|
||||
"engine_result_code": 0,
|
||||
"engine_result_message": "The transaction was applied. Only final in a validated ledger.",
|
||||
"tx_blob": "120002228000000024000000062019000000056840000000000001F4732103E498E35BC1E109C5995BD3AB0A6D4FFAB61B853C8F6010FABC5DABAF34478B617446304402207DE4EA9C8655E75BA01F96345B3F62074313EB42C15D9C4871E30F02202D2BA50220070E52AD308A31AC71E33BA342F31B68D1D1B2A7A3A3ED6E8552CA3DCF14FBB2701024A0228020D280D1A02BAD0D2EBC0528B92E9BF37AC3E2530832C2C52620307135156F1048701127A0258020E24D9E1473D4DF774F6D8E089067282034E4FA7ECACA2AD2E547953B2C113CBD81012081149A2AA667E1517EFA8A6B552AB2EDB859A99F26B282149A2AA667E1517EFA8A6B552AB2EDB859A99F26B2",
|
||||
"tx_json": {
|
||||
"Account": "rEhw9vD98ZrkY4tZPvkZst5H18RysqFdaB",
|
||||
"Condition": "A0258020E24D9E1473D4DF774F6D8E089067282034E4FA7ECACA2AD2E547953B2C113CBD810120",
|
||||
"Fee": "500",
|
||||
"Flags": 2147483648,
|
||||
"Fulfillment": "A0228020D280D1A02BAD0D2EBC0528B92E9BF37AC3E2530832C2C52620307135156F1048",
|
||||
"OfferSequence": 5,
|
||||
"Owner": "rEhw9vD98ZrkY4tZPvkZst5H18RysqFdaB",
|
||||
"Sequence": 6,
|
||||
"SigningPubKey": "03E498E35BC1E109C5995BD3AB0A6D4FFAB61B853C8F6010FABC5DABAF34478B61",
|
||||
"TransactionType": "EscrowFinish",
|
||||
"TxnSignature": "304402207DE4EA9C8655E75BA01F96345B3F62074313EB42C15D9C4871E30F02202D2BA50220070E52AD308A31AC71E33BA342F31B68D1D1B2A7A3A3ED6E8552CA3DCF14FBB2",
|
||||
"hash": "0E88368CAFC69A722ED829FAE6E2DD3575AE9C192691E60B5ACDF706E219B2BF"
|
||||
}
|
||||
}
|
||||
}
|
||||
</code></pre></div>
|
||||
</div>
|
||||
<p>Take note of the transaction's identifying <code>hash</code> value so you can check its final status when it is included in a validated ledger version.</p>
|
||||
<h3 id="7-wait-for-validation-1">7. Wait for validation</h3>
|
||||
<p>On the live network or the Ripple Test Net, you can wait 4-7 seconds for the ledger to close automatically.</p>
|
||||
<p>If you're running <code>rippled</code> in stand-alone mode, use the <a href="reference-rippled.html#ledger-accept"><code>ledger_accept</code> command</a> to manually close the ledger.</p>
|
||||
<h3 id="8-confirm-final-result-1">8. Confirm final result</h3>
|
||||
<p>Use the <a href="reference-rippled.html#tx"><code>tx</code> command</a> with the EscrowFinish transaction's identifying hash to check its final status. In particular, look in the transaction metadata for a <code>ModifiedNode</code> of type <code>AccountRoot</code> for the destination of the escrowed payment. The <code>FinalFields</code> of the object should reflect the increase in XRP in the <code>Balance</code> field.</p>
|
||||
<p>Request:</p>
|
||||
<pre><code class="json">{
|
||||
"id": 20,
|
||||
"command": "tx",
|
||||
"transaction": "52C4F626FE6F33699B6BE8ADF362836DDCE9B0B1294BFAA15D65D61501350BE6"
|
||||
}
|
||||
</code></pre>
|
||||
<p>Response:</p>
|
||||
<pre><code class="json">{
|
||||
"id": 20,
|
||||
"status": "success",
|
||||
"type": "response",
|
||||
"result": {
|
||||
"Account": "rEhw9vD98ZrkY4tZPvkZst5H18RysqFdaB",
|
||||
"Condition": "A0258020E24D9E1473D4DF774F6D8E089067282034E4FA7ECACA2AD2E547953B2C113CBD810120",
|
||||
"Fee": "500",
|
||||
"Flags": 2147483648,
|
||||
"Fulfillment": "A0228020D280D1A02BAD0D2EBC0528B92E9BF37AC3E2530832C2C52620307135156F1048",
|
||||
"OfferSequence": 2,
|
||||
"Owner": "rEhw9vD98ZrkY4tZPvkZst5H18RysqFdaB",
|
||||
"Sequence": 4,
|
||||
"SigningPubKey": "03E498E35BC1E109C5995BD3AB0A6D4FFAB61B853C8F6010FABC5DABAF34478B61",
|
||||
"TransactionType": "EscrowFinish",
|
||||
"TxnSignature": "3045022100925FEBE21C2E57F81C472A4E5869CAB1D0164C472A46532F39F6F9F7ED6846D002202CF9D9063ADC4CC0ADF4C4692B7EE165C5D124CAA855649389E245D993F41D4D",
|
||||
"date": 556838610,
|
||||
"hash": "52C4F626FE6F33699B6BE8ADF362836DDCE9B0B1294BFAA15D65D61501350BE6",
|
||||
"inLedger": 1771204,
|
||||
"ledger_index": 1771204,
|
||||
"meta": {
|
||||
"AffectedNodes": [
|
||||
{
|
||||
"ModifiedNode": {
|
||||
"FinalFields": {
|
||||
"Account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"Balance": "400100000",
|
||||
"Flags": 0,
|
||||
"OwnerCount": 0,
|
||||
"Sequence": 1
|
||||
},
|
||||
"LedgerEntryType": "AccountRoot",
|
||||
"LedgerIndex": "13F1A95D7AAB7108D5CE7EEAF504B2894B8C674E6D68499076441C4837282BF8",
|
||||
"PreviousFields": {
|
||||
"Balance": "400000000"
|
||||
},
|
||||
"PreviousTxnID": "795CBC8AFAAB9DC7BD9944C7FAEABF9BB0802A84520BC649213AD6A2C3256C95",
|
||||
"PreviousTxnLgrSeq": 1770775
|
||||
}
|
||||
},
|
||||
{
|
||||
"ModifiedNode": {
|
||||
"FinalFields": {
|
||||
"Flags": 0,
|
||||
"Owner": "rEhw9vD98ZrkY4tZPvkZst5H18RysqFdaB",
|
||||
"RootIndex": "4B4EBB6D8563075813D47491CC325865DFD3DC2E94889F0F39D59D9C059DD81F"
|
||||
},
|
||||
"LedgerEntryType": "DirectoryNode",
|
||||
"LedgerIndex": "4B4EBB6D8563075813D47491CC325865DFD3DC2E94889F0F39D59D9C059DD81F"
|
||||
}
|
||||
},
|
||||
{
|
||||
"ModifiedNode": {
|
||||
"FinalFields": {
|
||||
"Account": "rEhw9vD98ZrkY4tZPvkZst5H18RysqFdaB",
|
||||
"Balance": "9999898980",
|
||||
"Flags": 0,
|
||||
"OwnerCount": 0,
|
||||
"Sequence": 5
|
||||
},
|
||||
"LedgerEntryType": "AccountRoot",
|
||||
"LedgerIndex": "5F3B7107F4B524367A173A2B0EAB66E8CC4D2178C1B0C0528CB2F73A8B6BF254",
|
||||
"PreviousFields": {
|
||||
"Balance": "9999899480",
|
||||
"OwnerCount": 1,
|
||||
"Sequence": 4
|
||||
},
|
||||
"PreviousTxnID": "5C2A1E7B209A7404D3722A010D331A8C1C853109A47DDF620DE5E3D59F026581",
|
||||
"PreviousTxnLgrSeq": 1771042
|
||||
}
|
||||
},
|
||||
{
|
||||
"DeletedNode": {
|
||||
"FinalFields": {
|
||||
"Account": "rEhw9vD98ZrkY4tZPvkZst5H18RysqFdaB",
|
||||
"Amount": "100000",
|
||||
"Condition": "A0258020E24D9E1473D4DF774F6D8E089067282034E4FA7ECACA2AD2E547953B2C113CBD810120",
|
||||
"Destination": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"FinishAfter": 556838185,
|
||||
"Flags": 0,
|
||||
"OwnerNode": "0000000000000000",
|
||||
"PreviousTxnID": "795CBC8AFAAB9DC7BD9944C7FAEABF9BB0802A84520BC649213AD6A2C3256C95",
|
||||
"PreviousTxnLgrSeq": 1770775
|
||||
},
|
||||
"LedgerEntryType": "Escrow",
|
||||
"LedgerIndex": "DC524D17B3F650E7A215B332F418E54AE59B0DFC5392E74958B0037AFDFE8C8D"
|
||||
}
|
||||
}
|
||||
],
|
||||
"TransactionIndex": 1,
|
||||
"TransactionResult": "tesSUCCESS"
|
||||
},
|
||||
"validated": true
|
||||
}
|
||||
}
|
||||
</code></pre>
|
||||
<h2 id="look-up-escrows-by-sender">Look up escrows by sender</h2>
|
||||
<p>All pending escrows are stored in the ledger as <a href="reference-ledger-format.html#escrow">Escrow objects</a>. You can look up escrow nodes owned by your address using the <a href="reference-rippled.html#account-objects"><code>account_objects</code> method</a>.</p>
|
||||
<p>Request:</p>
|
||||
<div class="multicode" id="code-18"><ul class="codetabs"><li><a href="#code-18-0">Websocket</a></li></ul>
|
||||
|
||||
<div class="code_sample" id="code-18-0" style="position: static;"><pre><code class="json">{
|
||||
"id": 5,
|
||||
"command": "account_objects",
|
||||
"account": "rEhw9vD98ZrkY4tZPvkZst5H18RysqFdaB",
|
||||
"ledger_index": "validated",
|
||||
"type": "escrow"
|
||||
}
|
||||
</code></pre></div>
|
||||
</div>
|
||||
<p>Response:</p>
|
||||
<div class="multicode" id="code-19"><ul class="codetabs"><li><a href="#code-19-0">Websocket</a></li></ul>
|
||||
|
||||
<div class="code_sample" id="code-19-0" style="position: static;"><pre><code class="json">{
|
||||
"id": 5,
|
||||
"status": "success",
|
||||
"type": "response",
|
||||
"result": {
|
||||
"account": "rEhw9vD98ZrkY4tZPvkZst5H18RysqFdaB",
|
||||
"account_objects": [
|
||||
{
|
||||
"Account": "rEhw9vD98ZrkY4tZPvkZst5H18RysqFdaB",
|
||||
"Amount": "100000",
|
||||
"CancelAfter": 556927412,
|
||||
"Condition": "A0258020E24D9E1473D4DF774F6D8E089067282034E4FA7ECACA2AD2E547953B2C113CBD810120",
|
||||
"Destination": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"Flags": 0,
|
||||
"LedgerEntryType": "Escrow",
|
||||
"OwnerNode": "0000000000000000",
|
||||
"PreviousTxnID": "E22D1F6EB006CAD35E0DBD3B4F3748427055E4C143EBE95AA6603823AEEAD324",
|
||||
"PreviousTxnLgrSeq": 1772019,
|
||||
"index": "E2CF730A31FD419382350C9DBD8DB7CD775BA5AA9B97A9BE9AB07304AA217A75"
|
||||
}
|
||||
],
|
||||
"ledger_hash": "F2ABEA175F4AB871845B01CB51E4324DBA2C2553EC34448D4AB1EB0A3F2D8EFB",
|
||||
"ledger_index": 1772020,
|
||||
"validated": true
|
||||
}
|
||||
}
|
||||
</code></pre></div>
|
||||
</div>
|
||||
<p class="devportal-callout tip"><strong>Tip:</strong> If you don't know what <code>OfferSequence</code> to use in the <a href="reference-transaction-format.html#escrowfinish">EscrowFinish transaction</a> to execute an escrow, use the <a href="reference-rippled.html"><code>tx</code> method</a> to look up the transaction that created the escrow, using the identifying hash of the transaction in the Escrow's <code>PreviousTxnID</code> field. Use the <code>Sequence</code> value of that transaction as the <code>OfferSequence</code> value when finishing the escrow.</p>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<footer class="content-info" role="contentinfo">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-sm-12 absolute_bottom_footer">
|
||||
<div class="col-sm-8">
|
||||
<span>© 2013 - 2017 Ripple Labs, Inc. All Rights Reserved.</span>
|
||||
<span><a href="/terms-of-use/">Terms</a></span>
|
||||
<span><a href="/privacy-policy/">Privacy</a></span>
|
||||
</div>
|
||||
</div><!-- /.absolute_bottom_footer -->
|
||||
|
||||
</div><!-- /.row -->
|
||||
</div><!-- /.container -->
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,927 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<meta name="viewport" content="width=device-width">
|
||||
|
||||
<title>Gateway Guide - Ripple Developer Portal</title>
|
||||
|
||||
<!-- favicon -->
|
||||
<link rel="icon" href="favicon.ico" type="image/x-icon">
|
||||
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon">
|
||||
|
||||
<!-- jQuery -->
|
||||
<script src="assets/vendor/jquery-1.11.1.min.js"></script>
|
||||
|
||||
<!-- Custom Stylesheets. ripple.css includes bootstrap, font stuff -->
|
||||
<link href="assets/css/ripple.css" rel="stylesheet" />
|
||||
<link href="assets/css/devportal.css" rel="stylesheet" />
|
||||
|
||||
<!-- Bootstrap JS -->
|
||||
<script src="assets/vendor/bootstrap.min.js"></script>
|
||||
|
||||
|
||||
<!-- syntax highlighting -->
|
||||
<link rel="stylesheet" href="assets/vendor/docco.min.css" />
|
||||
<script src="assets/vendor/highlight.min.js"></script>
|
||||
|
||||
<!-- syntax selection js -->
|
||||
<script src="assets/js/multicodetab.js"></script>
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
$(".multicode").minitabs();
|
||||
hljs.initHighlighting();
|
||||
make_code_expandable();
|
||||
});
|
||||
</script>
|
||||
|
||||
<script src="assets/js/expandcode.js"></script>
|
||||
<script src="assets/js/fixsidebarscroll.js"></script>
|
||||
|
||||
<!-- fontawesome icons -->
|
||||
<link rel="stylesheet" href="assets/vendor/fontawesome/css/font-awesome.min.css" />
|
||||
|
||||
</head>
|
||||
|
||||
<body class="page page-template page-template-template-dev-portal page-template-template-dev-portal-php sidebar-primary wpb-js-composer js-comp-ver-3.6.2 vc_responsive">
|
||||
<header role="banner" class="banner navbar navbar-default navbar-fixed-top initial_header">
|
||||
<div class="container">
|
||||
<div class="navbar-header">
|
||||
<a href="index.html" class="navbar-brand"><img src="assets/img/ripple-logo-color.png" class="logo"></a>
|
||||
</div><!-- /.navbar-header -->
|
||||
<div class="nav">
|
||||
<div class="draft-warning">DRAFT PAGE</div>
|
||||
</div><!-- /.nav -->
|
||||
|
||||
</div><!-- /.container -->
|
||||
|
||||
<div class="subnav dev_nav">
|
||||
<div class="container">
|
||||
<ul id="menu-dev-menu" class="menu">
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">References <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="reference-rippleapi.html">RippleAPI</a></li>
|
||||
<li><a href="reference-rippled.html">rippled</a></li>
|
||||
<li><a href="reference-transaction-format.html">Transaction Format</a></li>
|
||||
<li><a href="reference-ledger-format.html">Ledger Format</a></li>
|
||||
<li><a href="reference-data-api.html">Ripple Data API v2</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorials <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="tutorial-multisign.html">How to Multi-Sign</a></li>
|
||||
<li><a href="tutorial-paychan.html">Payment Channels Tutorial</a></li>
|
||||
<li><a href="concept-issuing-and-operational-addresses.html">Issuing and Operational Addresses</a></li>
|
||||
<li><a href="tutorial-reliable-transaction-submission.html">Reliable Transaction Submission</a></li>
|
||||
<li><a href="tutorial-rippleapi-beginners-guide.html">RippleAPI Beginners Guide</a></li>
|
||||
<li><a href="tutorial-rippled-setup.html">rippled Setup</a></li>
|
||||
<li><a href="tutorial-gateway-guide.html">Gateway Guide</a></li>
|
||||
<li><a href="tutorial-listing-xrp.html">Listing XRP as an Exchange</a></li>
|
||||
<li><a href="tutorial-escrow.html">Escrow Tutorials</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Features <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="concept-accounts.html">Accounts</a></li>
|
||||
<li><a href="concept-amendments.html">Amendments</a></li>
|
||||
<li><a href="concept-consensus.html">Consensus Process</a></li>
|
||||
<li><a href="concept-reaching-consensus.html">Reaching Consensus in the XRP Ledger</a></li>
|
||||
<li><a href="concept-fee-voting.html">Fee Voting</a></li>
|
||||
<li><a href="concept-fees.html">Fees (Disambiguation)</a></li>
|
||||
<li><a href="concept-freeze.html">Freeze</a></li>
|
||||
<li><a href="concept-partial-payments.html">Partial Payments</a></li>
|
||||
<li><a href="concept-paths.html">Paths</a></li>
|
||||
<li><a href="concept-reserves.html">Reserves</a></li>
|
||||
<li><a href="concept-stand-alone-mode.html">Stand-Alone Mode</a></li>
|
||||
<li><a href="concept-transaction-cost.html">Transaction Cost</a></li>
|
||||
<li><a href="concept-transfer-fees.html">Transfer Fees</a></li>
|
||||
<li><a href="concept-noripple.html">Understanding the NoRipple flag</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Gateway Bulletins <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="gb-2015-06.html">GB-2015-06: Corrections to Autobridging</a></li>
|
||||
<li><a href="gb-2015-05.html">GB-2015-05: Historical Ledger Query Migration</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">API Tools <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="ripple-api-tool.html">WebSocket API Tool</a></li>
|
||||
<li><a href="data-api-v2-tool.html">Data API v2 Tool</a></li>
|
||||
<li><a href="tool-jsonrpc.html">rippled JSON-RPC Tool</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li><a href="https://github.com/ripple/ripple-dev-portal" title="GitHub">Site Source</a></li>
|
||||
</ul><!-- /#dev-menu -->
|
||||
</div><!-- /.subnav .container -->
|
||||
</div><!-- /.subnav -->
|
||||
</header>
|
||||
|
||||
|
||||
<div class="wrap container" role="document">
|
||||
<aside class="sidebar" role="complementary">
|
||||
<div class="dev_nav_wrapper">
|
||||
<div id="cont">
|
||||
<h5>In this category:</h5>
|
||||
<ul class="dev_nav_sidebar">
|
||||
<li class="level-1"><a href="index.html">Category: Tutorials</a></li>
|
||||
<li class="level-2"><a href="tutorial-multisign.html">How to Multi-Sign</a></li>
|
||||
<li class="level-2"><a href="tutorial-paychan.html">Payment Channels Tutorial</a></li>
|
||||
<li class="level-2"><a href="concept-issuing-and-operational-addresses.html">Issuing and Operational Addresses</a></li>
|
||||
<li class="level-2"><a href="tutorial-reliable-transaction-submission.html">Reliable Transaction Submission</a></li>
|
||||
<li class="level-2"><a href="tutorial-rippleapi-beginners-guide.html">RippleAPI Beginners Guide</a></li>
|
||||
<li class="level-2"><a href="tutorial-rippled-setup.html">rippled Setup</a></li>
|
||||
<li class="level-2"><a href="tutorial-gateway-guide.html">Gateway Guide</a></li>
|
||||
<li class="level-2"><a href="tutorial-listing-xrp.html">Listing XRP as an Exchange</a></li>
|
||||
<li class="level-2"><a href="tutorial-escrow.html">Escrow Tutorials</a></li>
|
||||
</ul>
|
||||
<hr />
|
||||
<h5>In this page:</h5>
|
||||
<ul class="dev_nav_sidebar" id="dactyl_toc_sidebar">
|
||||
<li class="level-1"><a href="#becoming-an-xrp-ledger-gateway">Becoming an XRP Ledger Gateway</a></li>
|
||||
<li class="level-2"><a href="#contact-information">Contact Information</a></li>
|
||||
<li class="level-2"><a href="#gateways-explained">Gateways Explained</a></li>
|
||||
<li class="level-3"><a href="#trust-lines-and-issuances">Trust Lines and Issuances</a></li>
|
||||
<li class="level-3"><a href="#xrp">XRP</a></li>
|
||||
<li class="level-3"><a href="#liquidity-and-currency-exchange">Liquidity and Currency Exchange</a></li>
|
||||
<li class="level-2"><a href="#suggested-business-practices">Suggested Business Practices</a></li>
|
||||
<li class="level-3"><a href="#hot-and-cold-wallets">Hot and Cold Wallets</a></li>
|
||||
<li class="level-2"><a href="#fees-and-revenue-sources">Fees and Revenue Sources</a></li>
|
||||
<li class="level-3"><a href="#choosing-fee-rates">Choosing Fee Rates</a></li>
|
||||
<li class="level-2"><a href="#gateway-compliance">Gateway Compliance</a></li>
|
||||
<li class="level-3"><a href="#know-your-customer-kyc">Know Your Customer (KYC)</a></li>
|
||||
<li class="level-3"><a href="#anti-money-laundering-aml-and-combating-the-financing-of-terrorism-cft">Anti-Money Laundering (AML) and Combating the Financing of Terrorism (CFT)</a></li>
|
||||
<li class="level-3"><a href="#source-of-funds">Source of Funds</a></li>
|
||||
<li class="level-3"><a href="#suspicious-activity-reporting">Suspicious Activity Reporting</a></li>
|
||||
<li class="level-3"><a href="#travel-rule">Travel Rule</a></li>
|
||||
<li class="level-3"><a href="#fee-disclosure-and-tracing-funds">Fee Disclosure and Tracing Funds</a></li>
|
||||
<li class="level-3"><a href="#office-of-foreign-assets-control-ofac">Office of Foreign Assets Control (OFAC)</a></li>
|
||||
<li class="level-3"><a href="#guidance-on-virtual-currency-and-money-service-business">Guidance on Virtual Currency and Money Service Business</a></li>
|
||||
<li class="level-1"><a href="#xrp-ledger-integration">XRP Ledger Integration</a></li>
|
||||
<li class="level-2"><a href="#before-integration">Before Integration</a></li>
|
||||
<li class="level-2"><a href="#sending-from-gateway-to-the-xrp-ledger">Sending from Gateway to the XRP Ledger</a></li>
|
||||
<li class="level-3"><a href="#requirements-for-sending-to-xrp-ledger">Requirements for Sending to XRP Ledger</a></li>
|
||||
<li class="level-2"><a href="#sending-from-xrp-ledger-to-gateway">Sending from XRP Ledger to Gateway</a></li>
|
||||
<li class="level-3"><a href="#requirements-for-receiving-from-xrp-ledger">Requirements for Receiving from XRP Ledger</a></li>
|
||||
<li class="level-2"><a href="#precautions">Precautions</a></li>
|
||||
<li class="level-2"><a href="#trading-on-ripple">Trading on Ripple</a></li>
|
||||
<li class="level-2"><a href="#freeze">Freeze</a></li>
|
||||
<li class="level-2"><a href="#authorized-accounts">Authorized Accounts</a></li>
|
||||
<li class="level-2"><a href="#source-and-destination-tags">Source and Destination Tags</a></li>
|
||||
<li class="level-2"><a href="#gateway-bulletins">Gateway Bulletins</a></li>
|
||||
<li class="level-1"><a href="#technical-details">Technical Details</a></li>
|
||||
<li class="level-2"><a href="#infrastructure">Infrastructure</a></li>
|
||||
<li class="level-3"><a href="#apis-and-middleware">APIs and Middleware</a></li>
|
||||
<li class="level-2"><a href="#tool-security">Tool Security</a></li>
|
||||
<li class="level-2"><a href="#defaultripple">DefaultRipple</a></li>
|
||||
<li class="level-2"><a href="#generating-source-and-destination-tags">Generating Source and Destination Tags</a></li>
|
||||
<li class="level-2"><a href="#disallowxrp">DisallowXRP</a></li>
|
||||
<li class="level-2"><a href="#requiredest">RequireDest</a></li>
|
||||
<li class="level-2"><a href="#requireauth">RequireAuth</a></li>
|
||||
<li class="level-3"><a href="#enabling-requireauth">Enabling RequireAuth</a></li>
|
||||
<li class="level-3"><a href="#authorizing-trust-lines">Authorizing Trust Lines</a></li>
|
||||
<li class="level-2"><a href="#robustly-monitoring-for-payments">Robustly Monitoring for Payments</a></li>
|
||||
<li class="level-2"><a href="#transferrate">TransferRate</a></li>
|
||||
<li class="level-3"><a href="#transferrate-with-operational-and-standby-addresses">TransferRate with Operational and Standby Addresses</a></li>
|
||||
<li class="level-2"><a href="#sending-payments-to-customers">Sending Payments to Customers</a></li>
|
||||
<li class="level-2"><a href="#bouncing-payments">Bouncing Payments</a></li>
|
||||
<li class="level-2"><a href="#reliable-transaction-submission">Reliable Transaction Submission</a></li>
|
||||
<li class="level-2"><a href="#rippletxt">ripple.txt</a></li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
<main class="main" role="main">
|
||||
<div class='content'>
|
||||
<h1 id="becoming-an-xrp-ledger-gateway">Becoming an XRP Ledger Gateway</h1>
|
||||
<p><strong>Gateways</strong> are the businesses that link the XRP Ledger to the rest of the world. An existing online financial institution can expand to act as a gateway in the the XRP Ledger. By becoming an XRP Ledger gateway, a financial services business can gain several advantages:</p>
|
||||
<ul>
|
||||
<li>By enabling its customers to send and receive value in the XRP Ledger, the business increases its value proposition to customers.</li>
|
||||
<li>By accepting payments from the XRP Ledger, the business increases the number of ways that customers can fund accounts at its business, even internationally.</li>
|
||||
<li>The business can use XRP Ledger-related services as a new source of revenue.</li>
|
||||
</ul>
|
||||
<p>This document explains the concepts and steps necessary to become an XRP Ledger gateway. In this document, we use a fictional online currency exchange named "ACME" and its customers as examples, to show how ACME can expand its business to include being an XRP Ledger gateway.</p>
|
||||
<h2 id="contact-information">Contact Information</h2>
|
||||
<p>You are not on your own. Ripple wants gateways to succeed, so we are here to help. Please contact us if you need help building and growing your gateway.</p>
|
||||
<ul>
|
||||
<li>Contact <a href="mailto:partners@ripple.com">partners@ripple.com</a> for enterprise-class integrations, infrastructure advice, and other business development needs.</li>
|
||||
<li>Contact <a href="mailto:support@ripple.com">support@ripple.com</a> for technical questions, clarifications, bug reports, and feature requests.</li>
|
||||
</ul>
|
||||
<h2 id="gateways-explained">Gateways Explained</h2>
|
||||
<p>Gateways are businesses that provide a way for money and other forms of value to move in and out of the XRP Ledger. There are three major models that gateways can follow, with different purposes and modes of operation.</p>
|
||||
<ul>
|
||||
<li>An <strong>Issuing Gateway</strong> receives money (or other assets of value) outside of the XRP Ledger, and creates issuances in the XRP Ledger. This provides a direct way for customers to get money in and out of the XRP Ledger. All currencies in the XRP Ledger, except for XRP, take the form of issuances tied to a specific issuing gateway.</li>
|
||||
<li>A <strong>Private Exchange</strong> holds XRP and lets its customers buy and sell that XRP in its own system. Most cryptocurrencies rely on private exchanges to provide a market for the cryptocurrency, but the XRP Ledger has a currency exchange built into the protocol itself.</li>
|
||||
<li><strong>Merchants</strong> accept payment within the XRP Ledger in exchange for goods and services in the outside world. Currently, Ripple (the company) does provide support for merchant operations using the XRP Ledger.</li>
|
||||
</ul>
|
||||
<p>This guide focuses on running an <strong>issuing gateway</strong>.</p>
|
||||
<h3 id="trust-lines-and-issuances">Trust Lines and Issuances</h3>
|
||||
<p>All assets in the XRP Ledger, except for the native cryptocurrency XRP, are represented as <em>issuances</em>, which are digital balances that represent currency or assets of value held by an issuer. Within the XRP Ledger, counterparties can send and trade issuances without requiring intervention from the issuer. Typically, a gateway sends issuances to customers when it receives money in systems and ledgers outside the XRP Ledger, and promises to send money to customers in outside systems in exchange for being repaid in issuances in the XRP Ledger. Issuances get their value from a gateway's agreement to honor the obligation that the issuances represent. No computer system can force an XRP Ledger gateway to honor that obligation.</p>
|
||||
<p>The XRP Ledger has a system of directional accounting relationships, called <em>trust lines</em>, to make sure that users only hold issuances from counterparties they trust.</p>
|
||||
<p>A "trust line" is link between two addresses in the XRP Ledger. A trust line represents an explicit statement of willingness to hold gateway debt obligations. When a customer sends money into the XRP Ledger, a gateway takes custody of those assets outside of Ripple, and sends issuances in the XRP Ledger to the customer's address. When a customer sends money out of the XRP Ledger, she makes an XRP Ledger payment to the gateway, and the gateway credits the customer in its own system of record, or in some other account.</p>
|
||||
<h3 id="xrp">XRP</h3>
|
||||
<p><strong>XRP</strong> is the native cryptocurrency of the XRP Ledger. Like issuances, XRP can be freely sent and exchanged among XRP Ledger addresses. Unlike issuances, XRP is not tied to an accounting relationship. XRP can be sent directly from any XRP Ledger address to any other, without going through a gateway or liquidity provider. This helps make XRP a convenient bridge currency. For more information on XRP, see the <a href="https://ripple.com/xrp-portal/">XRP Portal</a>.</p>
|
||||
<p>XRP also serves other purposes in the XRP Ledger, in particular as a protective measure against spamming the network. All XRP Ledger addresses need a small amount of XRP to pay the costs of maintaining the XRP Ledger. The <a href="concept-transaction-cost.html">transaction cost</a> and <a href="concept-reserves.html">reserve</a> are neutral fees denoted in XRP and not paid to any party.</p>
|
||||
<p>Issuing gateways do not need to accumulate or exchange XRP. They must only hold a small balance of XRP to send transactions through the network. The XRP equivalent of $10 USD should be enough for at least one year of transaction costs for a busy gateway.</p>
|
||||
<p>Private exchanges and liquidity providers may choose to hold additional XRP for trading. Ripple (the company) <strong>does not</strong> promote XRP as a speculative investment.</p>
|
||||
<h3 id="liquidity-and-currency-exchange">Liquidity and Currency Exchange</h3>
|
||||
<p>The XRP Ledger contains a currency exchange, where any user can place and fulfill bids to exchange XRP and <em>issuances</em> in any combination. Cross-currency payments automatically use the currency exchange to convert currency atomically when the transaction is executed. In this way, users who choose make offers in the distributed exchange provide the liquidity that makes the XRP Ledger useful.</p>
|
||||
<p>Currency traders who hold a gateway's issuances can provide liquidity to other popular currencies, without the gateway needing to float a large reserve in various destination currencies. The gateway also does not need to take on the risk of financial exchange. However, a gateway may still want to provide liquidity to XRP or other popular currencies at a baseline rate, especially when the gateway is new to the exchange. If you do provide liquidity, use a different address for trading than your issuing address.</p>
|
||||
<p>Third-party liquidity providers can use the <a href="reference-rippled.html"><code>rippled</code> APIs</a>, <a href="reference-rippleapi.html">RippleAPI JavaScript Library</a>, or a third-party client application to access the distributed exchange. Some client applications look up the addresses associated with a gateway using <a href="#rippletxt">ripple.txt</a>, so it can be helpful to publish a good ripple.txt.</p>
|
||||
<p>Contact <a href="mailto:partners@ripple.com">partners@ripple.com</a> for help establishing liquidity between your gateway and others.</p>
|
||||
<h2 id="suggested-business-practices">Suggested Business Practices</h2>
|
||||
<p>The value of a gateway's issuances in the XRP Ledger comes directly from the trust that customers can redeem them with the gateway when needed. We recommend the following precautions to reduce the risk of business interruptions:</p>
|
||||
<ul>
|
||||
<li>Use separate <a href="concept-issuing-and-operational-addresses.html">Issuing and Operational Addresses</a> to limit your risk profile on the network.</li>
|
||||
<li>Comply with anti-money-laundering regulations for your jurisdiction, such as the <a href="http://en.wikipedia.org/wiki/Bank_Secrecy_Act">Bank Secrecy Act</a>. This usually includes requirements to collect <a href="http://en.wikipedia.org/wiki/Know_your_customer">"Know-Your-Customer" (KYC) information</a>.</li>
|
||||
<li>Read and stay up-to-date with <a href="#gateway-bulletins">Gateway Bulletins</a>, which provide news and suggestions for XRP Ledger gateways.</li>
|
||||
<li>Publicize all your policies and fees.</li>
|
||||
</ul>
|
||||
<h3 id="hot-and-cold-wallets">Hot and Cold Wallets</h3>
|
||||
<p>In the XRP Ledger, financial institutions typically use multiple XRP Ledger addresses to minimize the risk associated with a compromised secret key. Ripple strongly recommends the following separation of roles:</p>
|
||||
<ul>
|
||||
<li>One <strong>issuing address</strong>, also known as a "cold wallet." This address is the hub of the financial institution's accounting relationships in the ledger, but sends as few transactions as possible. <!-- STYLE_OVERRIDE: cold wallet, wallet --></li>
|
||||
<li>One or more <strong>operational addresses</strong>, also known as "hot wallets." Automated, internet-connected systems use the secret keys to these addresses to conduct day-to-day business like transfers to customers and partners. <!-- STYLE_OVERRIDE: hot wallet, wallet --></li>
|
||||
<li>Optional <strong>standby addresses</strong>, also known as "warm wallets." Trusted human operators use these addresses to transfer money to the operational addresses. <!-- STYLE_OVERRIDE: warm wallet, wallet --></li>
|
||||
</ul>
|
||||
<p>For more information, see <a href="concept-issuing-and-operational-addresses.html">Issuing and Operational Addresses</a></p>
|
||||
<h2 id="fees-and-revenue-sources">Fees and Revenue Sources</h2>
|
||||
<p>There are several ways in which a gateway can seek to profit from XRP Ledger integration. These can include:</p>
|
||||
<ul>
|
||||
<li>Withdrawal and Deposit fees. Gateways typically charge a small fee (such as 1%) for the service of adding or removing money from the XRP Ledger. You have the power to determine the rate you credit people when they move money onto and off of the XRP Ledger through your gateway.</li>
|
||||
<li>Transfer fees. You can set a percentage fee to charge automatically when customers send each other issuances created by your issuing address. This amount is debited from the XRP Ledger, decreasing your obligation each time your issuances change hands. See <a href="#transferrate">TransferRate</a> for details.</li>
|
||||
<li>Indirect revenue from value added. XRP Ledger integration can provide valuable functionality for your customers that distinguishes your business from your competitors.</li>
|
||||
<li>Interest on XRP Ledger-backed funds. You can keep the collateral for the funds you issue in XRP Ledger in a bank account that earns interest. Make sure you can always access enough funds to service customer withdrawals.</li>
|
||||
<li><a href="#liquidity-and-currency-exchange">Financial Exchange</a>. A gateway can also make offers to buy and sell its issuances for other issuances in the XRP Ledger, providing liquidity to cross-currency payments and possibly making a profit. (As with all financial exchange, profits are not guaranteed.)</li>
|
||||
</ul>
|
||||
<h3 id="choosing-fee-rates">Choosing Fee Rates</h3>
|
||||
<p>Fees imposed by gateways are optional. Higher fees earn more revenue when a gateway's services are used. On the other hand, high fees discourage customers from using your services. Consider the fees that are charged by other gateways, especially ones issuing similar currencies, as well as traditional payment systems outside of the XRP Ledger, such as wire fees. Choosing the right fee structure is a matter of balancing your pricing with what the market is willing to pay.</p>
|
||||
<h2 id="gateway-compliance">Gateway Compliance</h2>
|
||||
<p>Gateways are responsible for complying with local regulations and reporting to the appropriate agencies. Regulations vary by country and state, but may include the reporting and compliance requirements described in the following sections.</p>
|
||||
<h3 id="know-your-customer-kyc">Know Your Customer (KYC)</h3>
|
||||
<p>Know Your Customer (KYC) refers to due diligence activities conducted by a financial institution to determine and verify the identity of its customers in order to prevent use of the institution for criminal activity. Criminal activity in financial terms may include money laundering, terrorist financing, financial fraud, and identity theft. Customers may be individuals, intermediaries, or businesses.</p>
|
||||
<p>The KYC process generally aims to:</p>
|
||||
<ul>
|
||||
<li>
|
||||
<p>Identify the customer (and, in the case of organizations and businesses, any beneficial owners)</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Understand the purpose and intended nature of the business relationship</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Understand the expected transaction activity.</p>
|
||||
</li>
|
||||
</ul>
|
||||
<p>KYC is critical for financial institutions and related businesses to mitigate risk, especially legal and reputational risk. Having an inadequate or nonexistent KYC program may result in civil and criminal penalties for the institution or individual employees.</p>
|
||||
<p>See also:</p>
|
||||
<ul>
|
||||
<li>
|
||||
<p><a href="https://www.ffiec.gov/bsa_aml_infobase/pages_manual/OLM_011.htm">The US-Standard on KYC</a></p>
|
||||
</li>
|
||||
<li>
|
||||
<p><a href="http://www.fatf-gafi.org/topics/fatfrecommendations/documents/fatf-recommendations.html">The Non-US Standard on KYC set by the Financial Action Task Force (FATF)</a></p>
|
||||
</li>
|
||||
</ul>
|
||||
<h3 id="anti-money-laundering-aml-and-combating-the-financing-of-terrorism-cft">Anti-Money Laundering (AML) and Combating the Financing of Terrorism (CFT)</h3>
|
||||
<p>Money laundering is the process of moving illegal funds by disguising the source, nature or ownership so that funds can be legally accessed or distributed via legitimate financial channels and credible institutions. In short, it is converting “dirty money” into “clean money.” Anti-Money Laundering (AML) refers to the laws and procedures designed to stop money laundering from occurring.</p>
|
||||
<p>Terrorist financing is the solicitation, collection, and/or provision of funds to organizations engaged in terrorist activity or organizations that support terrorism and its proliferation. Combating the Financing of Terrorism (CFT) refers to the process of identifying, reporting, and blocking flows of funds used to finance terrorism.</p>
|
||||
<p>See also:</p>
|
||||
<ul>
|
||||
<li>
|
||||
<p><a href="http://www.fatf-gafi.org/publications/fatfrecommendations/documents/fatf-recommendations.html">“International Standards on Combating Money Laundering and the Financing of Terrorism & Proliferation.” FATF, 2012</a></p>
|
||||
</li>
|
||||
<li>
|
||||
<p><a href="http://www.fatf-gafi.org/topics/methodsandtrends/documents/virtual-currency-definitions-aml-cft-risk.html">“Virtual Currencies: Key Definitions and Potential AML/CFT Risks.” FATF, 2014</a></p>
|
||||
</li>
|
||||
</ul>
|
||||
<h3 id="source-of-funds">Source of Funds</h3>
|
||||
<p>To prevent illicit funds from passing through their systems, financial institutions must be able to determine within reason if the source of a customer’s funds is linked to criminal activity.</p>
|
||||
<p>Determining the exact source of funds for every customer may not be administratively feasible. As a result, some regulatory authorities may not provide specific regulation or guidance for all accounts. In specific cases, however, authorities may require financial institutions to identify and report the source of funds. Guidance by the FATF recommends that where the risks of money laundering or terrorist financing are higher (commonly referred to as a “risk-based approach”), financial institutions conduct enhanced due diligence, including but not limited to determining the customer’s source of funds.</p>
|
||||
<h3 id="suspicious-activity-reporting">Suspicious Activity Reporting</h3>
|
||||
<p>If a financial institution suspects that funds may be related to criminal activity, the institution must file a Suspicious Activity Report (SAR) with the appropriate regulatory authority. Failure to report suspicious activity may result in in penalties for the institution.</p>
|
||||
<p>See also:</p>
|
||||
<ul>
|
||||
<li>
|
||||
<p><a href="https://www.ffiec.gov/bsa_aml_infobase/pages_manual/OLM_015.htm">Suspicious Activity Reporting Overview (USA FFIEC)</a></p>
|
||||
</li>
|
||||
<li>
|
||||
<p><a href="http://www.un.org/en/sc/ctc/docs/bestpractices/fatf/40recs-moneylaundering/fatf-rec16.pdf">FATF Recommendation 16: Reporting of suspicious transactions and compliance</a></p>
|
||||
</li>
|
||||
</ul>
|
||||
<h3 id="travel-rule">Travel Rule</h3>
|
||||
<p>The Travel Rule is a Bank Secrecy Act (BSA) rule requiring funds-transmitting financial institutions to forward certain information to the next financial institution if the funds transmittal equals or exceeds the USD equivalent of $3,000. The following information must be included in the transmittal order:</p>
|
||||
<ul>
|
||||
<li>The name of the transmittor,</li>
|
||||
<li>The account number of the transmittor, if used,</li>
|
||||
<li>The address of the transmittor,</li>
|
||||
<li>The identity of the transmittor's financial institution,</li>
|
||||
<li>The amount of the transmittal order,</li>
|
||||
<li>The execution date of the transmittal order, and</li>
|
||||
<li>The identity of the recipient's financial institution.</li>
|
||||
</ul>
|
||||
<p>See also:</p>
|
||||
<ul>
|
||||
<li><a href="http://www.fincen.gov/news_room/rp/advisory/html/advissu7.html">Additional information and background on the Travel Rule</a></li>
|
||||
</ul>
|
||||
<h3 id="fee-disclosure-and-tracing-funds">Fee Disclosure and Tracing Funds</h3>
|
||||
<ul>
|
||||
<li>
|
||||
<p>In the United States, Dodd Frank 1073 Electronic Fund Transfer Act (Regulation E) requires banks to provide information on cost and delivery terms for international payments originating in the US including exchange rate, fees, and the amount to be received by the designated recipient in the foreign country. "Pre-payment disclosure" is provided to a consumer when requesting an international electronic payment and “receipt disclosure” is provided to a consumer at the time consumer authorizes the transfer.</p>
|
||||
<p>See also:</p>
|
||||
<ul>
|
||||
<li><a href="http://www.consumerfinance.gov/remittances-transfer-rule-amendment-to-regulation-e/#rule">The Consumer Financial Protection Bureau description of the regulation and extensions for banks</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<p>In the European Union, EU Funds Transfer Regulation requires that the originator’s bank, the beneficiary’s bank, and any intermediary banks include certain details of the payer and payee in transaction details in an effort to detect, investigate, and prevent money laundering and terrorist financing.</p>
|
||||
<p>See also:</p>
|
||||
<ul>
|
||||
<li>
|
||||
<p><a href="http://eur-lex.europa.eu/LexUriServ/LexUriServ.do?uri=OJ:L:2006:345:0001:0009:EN:PDF">EU Regulation (EC) No 1781/2006 description</a></p>
|
||||
</li>
|
||||
<li>
|
||||
<p><a href="http://eur-lex.europa.eu/legal-content/EN/ALL/?uri=CELEX%3A32015R0847">Effective June 26, 2017: Regulation 2015/847 on information accompanying transfers of funds</a></p>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<h3 id="office-of-foreign-assets-control-ofac">Office of Foreign Assets Control (OFAC)</h3>
|
||||
<p>The Office of Foreign Assets Control (OFAC) is an agency of the US Department of Treasury that administers and enforces economic and trade sanctions in support of U.S. foreign policy and national security objectives. All U.S. persons and U.S. incorporated entities and their foreign branches must comply with OFAC regulations. Under OFAC regulations, U.S. financial institutions are prohibited—unless authorized by OFAC or expressly exempted by statute—from conducting transactions and other dealings with individuals, entities, or countries under sanctions or embargo programs administered and enforced by OFAC.</p>
|
||||
<p>See also:</p>
|
||||
<ul>
|
||||
<li><a href="https://www.treasury.gov/resource-center/faqs/Sanctions/Pages/ques_index.aspx">A list of OFAC resources</a></li>
|
||||
</ul>
|
||||
<h3 id="guidance-on-virtual-currency-and-money-service-business">Guidance on Virtual Currency and Money Service Business</h3>
|
||||
<ul>
|
||||
<li>
|
||||
<p>United States:</p>
|
||||
<ul>
|
||||
<li>
|
||||
<p><a href="http://www.fincen.gov/statutes_regs/guidance/html/FIN-2013-G001.html">FinCEN Guidance and Definitions around Virtual Currency, March 18, 2013</a></p>
|
||||
</li>
|
||||
<li>
|
||||
<p><a href="http://www.fincen.gov/news_room/nr/html/20140130.html">FinCEN Publishes Two Rulings on Virtual Currency Miners and Investors, January 30, 2014</a></p>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<p>Europe:</p>
|
||||
<ul>
|
||||
<li><a href="http://www.eba.europa.eu/documents/10180/657547/EBA-Op-2014-08+Opinion+on+Virtual+Currencies.pdf">European Banking Authority Opinion on Virtual Currencies, July 4, 2014</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<p>FATF Guidance for Money Service Businesses:</p>
|
||||
<ul>
|
||||
<li><a href="http://www.fatf-gafi.org/media/fatf/documents/reports/RBA%20Guidance%20for%20Money%20Service%20Businesses.pdf">Financial Action Task Force, July 2009</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<h1 id="xrp-ledger-integration">XRP Ledger Integration</h1>
|
||||
<h2 id="before-integration">Before Integration</h2>
|
||||
<p>Our example exchange, ACME, already accepts withdrawals and deposits from customers using some existing system, and uses its own system of record to track how much balance each user has with the exchange. Such a system can be modeled with a balance sheet and tracking how much currency each user has with ACME.</p>
|
||||
<p>In the following diagram, ACME Exchange starts with €5 on hand, including €1 that belongs to Bob, €2 that belongs to Charlie, and an additional €2 of equity that belongs to ACME itself. Alice deposits €5, so ACME adds her to its balance sheet and ends up with €10.</p>
|
||||
<p><img alt="Diagram: Alice sends €5 to ACME. ACME adds her balance to its balance sheet." src="img/e2g-01.png"/></p>
|
||||
<p><strong>Assumptions:</strong> To integrate with the XRP Ledger, we assume that an exchange such as ACME meets the following assumptions:</p>
|
||||
<ul>
|
||||
<li>ACME already has a system to accept deposits and withdrawals from some outside payment source.</li>
|
||||
<li>ACME waits for deposits to clear before crediting them in ACME's system of record.</li>
|
||||
<li>ACME always keeps enough funds on-hand to pay withdrawals on demand, subject to their terms and conditions.<ul>
|
||||
<li>ACME can set fees, minimum withdrawals, and delay times for deposits and withdrawals as their business model demands.</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<h2 id="sending-from-gateway-to-the-xrp-ledger">Sending from Gateway to the XRP Ledger</h2>
|
||||
<p>XRP Ledger payments can automatically bridge between currencies, but an issuing gateway normally only sends single-currency payments that go directly to customers. This means debiting a customer's current balance in your system, and then sending the equivalent amount of issuances in the XRP Ledger to the customer's XRP Ledger address.</p>
|
||||
<p>An example flow for a payment into the XRP Ledger:</p>
|
||||
<ol>
|
||||
<li>Alice asks to send €3 of her ACME balance into the XRP Ledger.</li>
|
||||
<li>In its system of record, ACME debits Alice's balance €3.</li>
|
||||
<li>ACME submits an XRP Ledger transaction, sending €3 to Alice's XRP Ledger address. The €3 is marked in the XRP Ledger as being "issued" by ACME (3 EUR.ACME).</li>
|
||||
</ol>
|
||||
<p><strong>Assumptions:</strong></p>
|
||||
<ul>
|
||||
<li>Alice already has an address in the XRP Ledger separate from her ACME account. Alice manages her XRP Ledger address using a third-party client application.</li>
|
||||
</ul>
|
||||
<p><img alt="Diagram: ACME issues 3 EUR.ACME to Alice on the XRP Ledger" src="img/e2g-02.png"/></p>
|
||||
<h3 id="requirements-for-sending-to-xrp-ledger">Requirements for Sending to XRP Ledger</h3>
|
||||
<p>There are several prerequisites that ACME must meet for this to happen:</p>
|
||||
<ul>
|
||||
<li>ACME sets aside money that is issued in the XRP Ledger. ACME can query the XRP Ledger to see who holds its issuances at any time. There are several ways ACME may do this:<ul>
|
||||
<li>ACME may create a XRP Ledger collateral account in ACME's system of record.</li>
|
||||
<li>ACME can store the funds allocated to the XRP Ledger in a separate bank account.</li>
|
||||
<li>If ACME is a cryptocurrency exchange, ACME can create a separate wallet to hold the funds allocated to the XRP Ledger, as publicly-verifiable proof to customers that the gateway is solvent.</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>ACME must control an address in the XRP Ledger. Ripple's best practices recommend using a separate issuing address and operational address. See <a href="concept-issuing-and-operational-addresses.html">Issuing and Operational Addresses</a> for details.<ul>
|
||||
<li>ACME must enable the <a href="#defaultripple">DefaultRipple Flag</a> on its issuing address for customers to send and receive its issuances.</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>Alice must create an accounting relationship (trust line) from her XRP Ledger address to ACME's issuing address. She can do this from any XRP Ledger client application as long as she knows ACME's issuing address.<ul>
|
||||
<li>ACME should publicize its issuing address on its website where customers can find it. It can also use <a href="#rippletxt">ripple.txt</a> to publish the issuing address to automated systems.</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>ACME must create a user interface for Alice to send funds from ACME into the XRP Ledger.<ul>
|
||||
<li>ACME needs to know Alice's XRP Ledger address. ACME can have Alice input her XRP Ledger addresss as part of the interface, or ACME can require Alice to input and verify her XRP Ledger address in advance.</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<p>See <a href="#sending-payments-to-customers">Sending Payments to Customers</a> for an example of how to send payments into the XRP Ledger.</p>
|
||||
<h2 id="sending-from-xrp-ledger-to-gateway">Sending from XRP Ledger to Gateway</h2>
|
||||
<p>A payment out of the XRP Ledger means the Gateway receives a payment in the XRP Ledger, and credits a user in the gateway's system of record.</p>
|
||||
<p>An example flow of a payment out of the XRP Ledger:</p>
|
||||
<ol>
|
||||
<li>Bob sends an XRP Ledger transaction of €1 to ACME's issuing address.</li>
|
||||
<li>In ACME's system of record, ACME credits Bob's balance €1.</li>
|
||||
</ol>
|
||||
<p>Payments going from the XRP Ledger to a gateway can be single-currency or cross-currency payments. The gateway's issuing address can only receive issuances it created (or XRP).</p>
|
||||
<h3 id="requirements-for-receiving-from-xrp-ledger">Requirements for Receiving from XRP Ledger</h3>
|
||||
<p>In addition to the <a href="#requirements-for-sending-to-xrp-ledger">requirements for sending into the XRP Ledger</a>, there are several prerequisites that ACME must meet to process payments coming from the XRP Ledger:</p>
|
||||
<ul>
|
||||
<li>ACME must monitor its XRP Ledger addresses for incoming payments.</li>
|
||||
<li>ACME must know which user to credit in its system of record for the incoming payments.<ul>
|
||||
<li>We recommend that ACME should <a href="#bouncing-payments">bounce any unrecognized incoming payments</a> back to their sender.</li>
|
||||
<li>Typically, the preferred method of recognizing incoming payments is through <a href="#source-and-destination-tags">destination tags</a>.</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<h2 id="precautions">Precautions</h2>
|
||||
<p>Processing payments to and from the XRP Ledger naturally comes with some risks, so a gateway should be sure to take care in implementing these processes. We recommend the following precautions:</p>
|
||||
<ul>
|
||||
<li>Protect yourself against reversible deposits. XRP Ledger payments are irreversible, but many electronic money systems like credit cards or PayPal are not. Scammers can abuse this to take their fiat money back by canceling a deposit after receiving Ripple issuances.</li>
|
||||
<li>When sending into the XRP Ledger, specify the issuing address as the issuer of the currency. Otherwise, you might accidentally use paths that deliver the same currency issued by other addresses.</li>
|
||||
<li>Before sending a payment into the XRP Ledger, double check the cost of the payment. A payment from your operational address to a customer should not cost more than the destination amount plus any <a href="#transferrate">transfer fee</a> you have set.</li>
|
||||
<li>Before processing a payment out of Ripple, make sure you know the customer's identity. This makes it harder for anonymous attackers to scam you. Most anti-money-laundering regulations require this anyway. This is especially important because the users sending money from the XRP Ledger could be different than the ones that initially received the money in the XRP Ledger.</li>
|
||||
<li>Follow the guidelines for <a href="#reliable-transaction-submission">reliable transaction submission</a> when sending XRP Ledger transactions.</li>
|
||||
<li><a href="#robustly-monitoring-for-payments">Robustly monitor for incoming payments</a>, and read the correct amount. Don't mistakenly credit someone the full amount if they only sent a <a href="reference-transaction-format.html#partial-payments">partial payment</a>.</li>
|
||||
<li>Track your obligations and balances within the XRP Ledger, and compare with the assets in your collateral account. If they do not match up, stop processing withdrawals and deposits until you resolve the discrepancy.</li>
|
||||
<li>Avoid ambiguous situations. We recommend the following:<ul>
|
||||
<li>Enable the <a href="#disallowxrp"><code>DisallowXRP</code> flag</a> for the issuing address and all operational addresses, so customers do not accidentally send you XRP. (Private exchanges should <em>not</em> set this flag, since they trade XRP normally.)</li>
|
||||
<li>Enable the <a href="#requiredest"><code>RequireDest</code> flag</a> for the issuing address and all operational addresses, so customers do not accidentally send a payment without the destination tag to indicate who should be credited.</li>
|
||||
<li>Enable the <a href="#requireauth"><code>RequireAuth</code> flag</a> on all operational addresses so they cannot issue currency by accident.</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>Monitor for suspicious or abusive behavior. For example, a user could repeatedly send funds into and out of the XRP Ledger, as a denial of service attack that effectively empties an operational address's balance. Suspend customers whose addresses are involved in suspicious behavior by not processing their XRP Ledger payments.</li>
|
||||
</ul>
|
||||
<h2 id="trading-on-ripple">Trading on Ripple</h2>
|
||||
<p>After the issuances have been created in the XRP Ledger, they can be freely transferred and traded by XRP Ledger users. There are several consequences of this situation:</p>
|
||||
<ul>
|
||||
<li>Anyone can buy/sell EUR.ACME on Ripple. If ACME issues multiple currencies on Ripple, a separate trust line is necessary for each.<ul>
|
||||
<li>This includes XRP Ledger users who do not have an account in ACME Exchange's systems. To withdraw the funds successfully from ACME, users still have to register with ACME.</li>
|
||||
<li>Optionally, ACME uses the <a href="#authorized-accounts">Authorized Accounts</a> feature to limit who can hold EUR.ACME in the XRP Ledger.</li>
|
||||
<li>If ACME determines that a customer has acted in bad faith, ACME can <a href="#freeze">Freeze</a> that user's accounting relationships to ACME in the XRP Ledger, so that the user can no longer trade in the gateway's issuances.</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>XRP Ledger users trading and sending EUR.ACME to one another requires no intervention by ACME.</li>
|
||||
<li>All exchanges and balances in the XRP Ledger are publicly viewable.</li>
|
||||
</ul>
|
||||
<p>The following diagram depicts an XRP Ledger payment sending 2EUR.ACME from Alice to Charlie. ACME can query the XRP Ledger to see updates to its balances any time after the transaction has occurred:</p>
|
||||
<p><img alt="Diagram: Alice's sends 2 EUR.ACME from her trust line to Charlie's" src="img/e2g-03.png"/></p>
|
||||
<h2 id="freeze">Freeze</h2>
|
||||
<p>A gateway can freeze accounting relationships in the XRP Ledger to meet regulatory requirements:</p>
|
||||
<ul>
|
||||
<li>Gateways can freeze individual accounting relationships, in case a customer address shows suspicious activity or violates a gateway's terms of use.</li>
|
||||
<li>Gateways can freeze all accounting relationships to their issuing address, in case of a major security compromise or for migrating to a new issuing address.</li>
|
||||
<li>Furthermore, gateways can permanently opt out of their ability to freeze accounting relationships. This allows a gateway to assure its customers that it will continue to provide "physical-money-like" services. <!-- STYLE_OVERRIDE: will --></li>
|
||||
</ul>
|
||||
<p>For more information, see the <a href="concept-freeze.html">Freeze article</a>.</p>
|
||||
<h2 id="authorized-accounts">Authorized Accounts</h2>
|
||||
<p>The XRP Ledger's Authorized Accounts feature enables a gateway to limit who can hold that gateway's issuances, so that unknown XRP Ledger addresses cannot hold the currency the gateway issues. Ripple feels this is <em>not necessary</em> in most cases, since gateways have full control over the process of redeeming Ripple balances for value in the outside world. (You can collect customer information and impose limits on withdrawals at that stage without worrying about what happens within the XRP Ledger.)</p>
|
||||
<p>To use the Authorized Accounts feature, a gateway enables the <code>RequireAuth</code> flag for its issuing address, and then individually approves each accounting relationship. An address can only hold funds issued by a gateway after its accounting relationship with that gateway is approved.</p>
|
||||
<p>The transaction to authorize an accounting relationship must be signed by the issuing address, which unfortunately means an increased risk exposure for that address. The process for sending funds into the XRP Ledger with RequireAuth enabled looks like the following:</p>
|
||||
<ol>
|
||||
<li>ACME publishes its issuing address to customers.</li>
|
||||
<li>Alice creates an accounting relationship from her XRP Ledger address to ACME's issuing address, indicating that she is willing to hold ACME's issuances.</li>
|
||||
<li>ACME's issuing address sends a transaction authorizing Alice's accounting relationship.</li>
|
||||
</ol>
|
||||
<p>See <a href="#requireauth">RequireAuth</a> for technical details on how to use Authorized Accounts.</p>
|
||||
<h2 id="source-and-destination-tags">Source and Destination Tags</h2>
|
||||
<p><em>Destination Tags</em> are a feature of XRP Ledger payments can be used to indicate the beneficiary or destination for a payment. For example, an XRP Ledger payment to a gateway may include a destination tag to indicate which customer should be credited for the payment. A gateway should keep a mapping of destination tags to accounts in the gateway's system of record.</p>
|
||||
<p>Similarly, <em>Source Tags</em> 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 bounce the payment. When you bounce an incoming payment, use the Source Tag from the incoming payment as the Destination Tag of the outgoing (bounce) payment.</p>
|
||||
<p>We recommend providing several kinds of Destination Tags for different purposes:</p>
|
||||
<ul>
|
||||
<li>Direct mappings to customer accounts</li>
|
||||
<li>Matching the Source Tags on outgoing payments (in case your payments get bounced)</li>
|
||||
<li>Tags for quotes, which expire</li>
|
||||
<li>Other disposable destination tags that customers can generate.</li>
|
||||
</ul>
|
||||
<p>See <a href="#generating-source-and-destination-tags">Generating Source and Destination Tags</a> for recommendations on the technical details of making and using Source Tags and Destination Tags.</p>
|
||||
<h2 id="gateway-bulletins">Gateway Bulletins</h2>
|
||||
<p>Historically, Ripple (the company) issued gateway bulletins to introduce new features or discuss topics related to compliance and risk. Gateway Bulletins are listed here in reverse chronological order.</p>
|
||||
<ul>
|
||||
<li>May 13, 2015 - <a href="gb-2015-06.html">GB-2015-06 Gateway Bulletin: Corrections to Autobridging</a></li>
|
||||
<li>April 17, 2015 - <a href="gb-2015-05.html">GB-2015-05 Historical Ledger Query Migration</a></li>
|
||||
<li>March 13, 2015 - <a href="https://ripple.com/files/GB-2015-04.pdf">GB-2015-04 Action Required: Default Ripple Flag (PDF)</a></li>
|
||||
<li>March 3, 2015 - <a href="https://ripple.com/files/GB-2015-03.pdf">GB-2015-03 Gateway Advisory: FinCEN Ruling on MoneyGram Compliance Program (PDF)</a></li>
|
||||
<li>March 2, 2015 (Updated) - <a href="https://ripple.com/files/GB-2015-02.pdf">GB-2015-02 New Standards: How to be Featured on Ripple Trade and Ripple Charts (PDF)</a></li>
|
||||
<li>January 5, 2015 - <a href="https://ripple.com/files/GB-2015-01.pdf">GB-2015-01 Gateway Advisory: Reliable Transaction Submission (PDF)</a></li>
|
||||
<li>December 18, 2014 - <a href="https://ripple.com/files/GB-2014-08.pdf">GB-2014-08 Gateway Advisory: Recent FinCEN Rulings (PDF)</a></li>
|
||||
<li>November 4, 2014 -<a href="https://ripple.com/files/GB-2014-07.pdf">GB-2014-07 Gateway Advisory: FATF Standards (PDF)</a></li>
|
||||
<li>October 17, 2014 -<a href="https://ripple.com/files/GB-2014-06.pdf">GB-2014-06 Gateway Advisory: Partial Payment Flag (PDF)</a></li>
|
||||
<li>September 24, 2014 - <a href="https://ripple.com/files/GB-2014-05.pdf">GB-2014-05 Gateway Advisory: EBA Opinion On Virtual Currency (PDF)</a></li>
|
||||
<li>September 11, 2014 - <a href="https://ripple.com/files/GB-2014-04.pdf">GB-2014-04 Gateway Advisory: CFPB Opinion on Virtual Currency (PDF)</a></li>
|
||||
<li>August 19, 2014 - <a href="https://ripple.com/files/GB-2014-03.pdf">GB-2014-03 Updated Feature: Trust Lines UI (PDF)</a></li>
|
||||
<li>August 1, 2014 - <a href="https://ripple.com/files/GB-2014-02.pdf">GB-2014-02 New Feature: Balance Freeze (PDF)</a></li>
|
||||
<li>April 23, 2014, Updated August 14, 2014 -<a href="https://ripple.com/files/GB-2014-01.pdf">GB-2014-01 New Feature: Ripple Names (PDF)</a></li>
|
||||
</ul>
|
||||
<h1 id="technical-details">Technical Details</h1>
|
||||
<h2 id="infrastructure">Infrastructure</h2>
|
||||
<p>For the gateway's own security as well as the stability of the network, Ripple recommends that each gateway run its own <code>rippled</code> servers. Ripple provides detailed and individualized recommendations to businesses interested in running a significant XRP-based business.</p>
|
||||
<p>Contact <a href="mailto:partners@ripple.com">partners@ripple.com</a> to see how Ripple can help.</p>
|
||||
<h3 id="apis-and-middleware">APIs and Middleware</h3>
|
||||
<p>There are several interfaces you can use to connect to the XRP Ledger, depending on your needs and your existing software:</p>
|
||||
<ul>
|
||||
<li><a href="reference-rippled.html"><code>rippled</code></a> provides JSON-RPC and WebSocket APIs that can be used as a low-level interface to all core XRP Ledger functionality.</li>
|
||||
<li><a href="reference-rippleapi.html">RippleAPI</a> provides a simplified API for JavaScript applications.</li>
|
||||
</ul>
|
||||
<h2 id="tool-security">Tool Security</h2>
|
||||
<p>Any time you submit an XRP Ledger transaction, it must be signed using your secret key. The secret key gives full control over your XRP Ledger address. <strong>Never</strong> send your secret key to a server operated by someone else. Either use your own <code>rippled</code> server, or sign the transactions locally before sending them to a <code>rippled</code> server.</p>
|
||||
<p>The examples in this document show API methods that include a secret key. This is only safe if you control <code>rippled</code> server yourself, <em>and</em> you connect to it over a connection that is secure from outside listeners. (For example, you could connect over a loopback (localhost) network, a private subnet, or an encrypted VPN.) Alternatively, you could use <a href="reference-rippleapi.html">RippleAPI</a> to sign transactions locally before submitting them to a third-party server.</p>
|
||||
<h2 id="defaultripple">DefaultRipple</h2>
|
||||
<p>The DefaultRipple flag controls whether the balances in an accounting relationship <a href="concept-noripple.html">allowed to ripple</a> by default. Rippling is what allows customers to trade issuances, so a gateway must allow rippling on all the accounting relationships to its issuing address.</p>
|
||||
<p>Before asking customers to create accounting relationships to its issuing address, a gateway should enable the DefaultRipple flag on that address. Otherwise, the gateway must individually disable the NoRipple flag for each accounting relationship that other addresses have created.</p>
|
||||
<p>The following is an example of using a locally-hosted <code>rippled</code>'s <a href="reference-rippled.html#submit"><code>submit</code> command</a> to send an AccountSet transaction to enable the DefaultRipple flag:</p>
|
||||
<p>Request:</p>
|
||||
<pre><code>POST http://localhost:8088/
|
||||
{
|
||||
"method": "submit",
|
||||
"params": [
|
||||
{
|
||||
"secret": "sn3nxiW7v8KXzPzAqzyHXbSSKNuN9",
|
||||
"tx_json": {
|
||||
"Account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"Fee": "15000",
|
||||
"Flags": 0,
|
||||
"SetFlag": 8,
|
||||
"TransactionType": "AccountSet"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
</code></pre>
|
||||
<p class="devportal-callout caution"><strong>Caution:</strong> Never submit a secret key to a server you do not control. Do not send a secret key unencrypted over the network.</p>
|
||||
<p>Response:</p>
|
||||
<pre><code>{
|
||||
"result": {
|
||||
"engine_result": "tesSUCCESS",
|
||||
"engine_result_code": 0,
|
||||
"engine_result_message": "The transaction was applied. Only final in a validated ledger.",
|
||||
"status": "success",
|
||||
"tx_blob": "1200032200000000240000003E202100000008684000000000003A98732103AB40A0490F9B7ED8DF29D246BF2D6269820A0EE7742ACDD457BEA7C7D0931EDB74473045022100D8F2DEF27DE313E3F0D1E189BF5AC8879F591045950E2A33787C3051169038C80220728A548F188F882EA40A416CCAF2AC52F3ED679563BBE1BAC014BB9E773A333581144B4E9C06F24296074F7BC48F92A97916C6DC5EA9",
|
||||
"tx_json": {
|
||||
"Account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"Fee": "15000",
|
||||
"Flags": 0,
|
||||
"Sequence": 62,
|
||||
"SetFlag": 8,
|
||||
"SigningPubKey": "03AB40A0490F9B7ED8DF29D246BF2D6269820A0EE7742ACDD457BEA7C7D0931EDB",
|
||||
"TransactionType": "AccountSet",
|
||||
"TxnSignature": "3045022100D8F2DEF27DE313E3F0D1E189BF5AC8879F591045950E2A33787C3051169038C80220728A548F188F882EA40A416CCAF2AC52F3ED679563BBE1BAC014BB9E773A3335",
|
||||
"hash": "665B27B64CE658704FFD326A4FE2F5F5B5E67EACA61DE08258A59D35B883E1D5"
|
||||
}
|
||||
}
|
||||
}
|
||||
</code></pre>
|
||||
<p>To confirm that an address has DefaultRipple enabled, look up the address using the <a href="reference-rippled.html#account-info">account_info command</a>, specifying a validated ledger version. Use <a href="https://en.wikipedia.org/wiki/Bitwise_operation#AND">a bitwise-AND operator</a> to compare the <code>Flags</code> field with 0x00800000 (the <a href="reference-ledger-format.html#accountroot-flags">ledger flag lsfDefaultRipple</a>). If the result of the bitwise-AND operation is nonzero, then the address has DefaultRipple enabled.</p>
|
||||
<h2 id="generating-source-and-destination-tags">Generating Source and Destination Tags</h2>
|
||||
<p>You need a scheme to create Source and Destination tags for your customers and payments. (See <a href="#source-and-destination-tags">Source and Destination Tags</a> for an explanation of what Source and Destination Tags are.)</p>
|
||||
<p>For greater privacy and security, we recommend <em>not</em> using monotonically-incrementing numbers as destination tags that correlate 1:1 with customers. Instead, we recommend using convenient internal IDs, but mapping those to destination tags using a quick hash or cipher function such as <a href="http://en.wikipedia.org/wiki/Hasty_Pudding_cipher">Hasty Pudding</a>. You should set aside ranges of internal numbers for different uses of destination tags.</p>
|
||||
<p>After passing the internal numbers through your hash function, you can use the result as a destination tag. To be safe, you should check for collisions. Do not reuse destination tags unless they have explicit expiration dates (like quotes and customer-generated tags).</p>
|
||||
<p>We recommend making a user interface to generate a destination tag on-demand when a customer intends to send money to the gateway. Then, consider that destination tag valid only for a payment with the expected amount. Later, bounce any other transactions that reuse the same destination tag.</p>
|
||||
<p>Enable the <a href="#requiredest">RequireDest</a> flag on your issuing and operational addresses so that customers must use a destination tag to indicate where funds should go when they send XRP Ledger payments to your gateway.</p>
|
||||
<h2 id="disallowxrp">DisallowXRP</h2>
|
||||
<p>The DisallowXRP setting (<code>disallowIncomingXRP</code> in RippleAPI) is designed to discourage XRP Ledger users from sending XRP to an address by accident. This reduces the costs and effort of bouncing undesired payments, if your gateway does not trade XRP. The DisallowXRP flag is not strictly enforced, because doing so could allow addresses to become permanently unusable if they run out of XRP. Client applications should honor the DisallowXRP flag by default.</p>
|
||||
<p>An issuing gateway that does not trade XRP should enable the DisallowXRP flag on the gateway's issuing and operational addresses. A private exchange that trades in XRP should only enable the DisallowXRP flag on addresses that are not expected to receive XRP.</p>
|
||||
<p>The following is an example of using a locally-hosted <code>rippled</code>'s <a href="reference-rippled.html#submit"><code>submit</code> command</a> to send an AccountSet transaction to enable the DisallowXRP flag:</p>
|
||||
<p>Request:</p>
|
||||
<pre><code>POST http://localhost:8088/
|
||||
{
|
||||
"method": "submit",
|
||||
"params": [
|
||||
{
|
||||
"secret": "sn3nxiW7v8KXzPzAqzyHXbSSKNuN9",
|
||||
"tx_json": {
|
||||
"Account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"Fee": "10000",
|
||||
"Flags": 0,
|
||||
"SetFlag": 3,
|
||||
"TransactionType": "AccountSet"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
</code></pre>
|
||||
<p class="devportal-callout caution"><strong>Caution:</strong> Never submit a secret key to a server you do not control. Do not send a secret key unencrypted over the network.</p>
|
||||
<p>Response:</p>
|
||||
<pre><code>{
|
||||
"result": {
|
||||
"engine_result": "tesSUCCESS",
|
||||
"engine_result_code": 0,
|
||||
"engine_result_message": "The transaction was applied. Only final in a validated ledger.",
|
||||
"status": "success",
|
||||
"tx_blob": "12000322000000002400000164202100000003684000000000002710732103AB40A0490F9B7ED8DF29D246BF2D6269820A0EE7742ACDD457BEA7C7D0931EDB74473045022100C2E38177E92C3998EB2C22978595784BC4CABCF7D57DE71FCF6CF162FB683A1D02205942D42C440D860B4CF7BB0DF77E4F2C529695854835B2F76DC2D09644FCBB2D81144B4E9C06F24296074F7BC48F92A97916C6DC5EA9",
|
||||
"tx_json": {
|
||||
"Account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"Fee": "10000",
|
||||
"Flags": 0,
|
||||
"Sequence": 356,
|
||||
"SetFlag": 3,
|
||||
"SigningPubKey": "03AB40A0490F9B7ED8DF29D246BF2D6269820A0EE7742ACDD457BEA7C7D0931EDB",
|
||||
"TransactionType": "AccountSet",
|
||||
"TxnSignature": "3045022100C2E38177E92C3998EB2C22978595784BC4CABCF7D57DE71FCF6CF162FB683A1D02205942D42C440D860B4CF7BB0DF77E4F2C529695854835B2F76DC2D09644FCBB2D",
|
||||
"hash": "096A89DA55A6A1C8C9EE1BCD15A8CADCC52E6D2591393F680243ECEB93161B33"
|
||||
}
|
||||
}
|
||||
}
|
||||
</code></pre>
|
||||
<h2 id="requiredest">RequireDest</h2>
|
||||
<p>The <code>RequireDest</code> setting (<code>requireDestinationTag</code> in RippleAPI) is designed to prevent customers from sending payments to your address while accidentally forgetting the <a href="#source-and-destination-tags">destination tag</a> that identifies who should be credited for the payment. When enabled, the XRP Ledger rejects any payment to your address that does not specify a destination tag.</p>
|
||||
<p>We recommend enabling the <code>RequireDest</code> flag on all gateway issuing and operational addresses.</p>
|
||||
<p>The following is an example of using a locally-hosted <code>rippled</code>'s <a href="reference-rippled.html#submit"><code>submit</code> command</a> to send an AccountSet transaction to enable the <code>RequireDest</code> flag:</p>
|
||||
<p>Request:</p>
|
||||
<pre><code>POST http://localhost:5005/
|
||||
Content-Type: application/json
|
||||
{
|
||||
"method": "submit",
|
||||
"params": [
|
||||
{
|
||||
"secret": "sn3nxiW7v8KXzPzAqzyHXbSSKNuN9",
|
||||
"tx_json": {
|
||||
"Account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"Fee": "15000",
|
||||
"Flags": 0,
|
||||
"SetFlag": 1,
|
||||
"TransactionType": "AccountSet"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
</code></pre>
|
||||
<p class="devportal-callout caution"><strong>Caution:</strong> Never submit a secret key to a server you do not control. Do not send a secret key unencrypted over the network.</p>
|
||||
<p>Response:</p>
|
||||
<pre><code>200 OK
|
||||
{
|
||||
"result": {
|
||||
"engine_result": "tesSUCCESS",
|
||||
"engine_result_code": 0,
|
||||
"engine_result_message": "The transaction was applied. Only final in a validated ledger.",
|
||||
"status": "success",
|
||||
"tx_blob": "12000322000000002400000161202100000003684000000000003A98732103AB40A0490F9B7ED8DF29D246BF2D6269820A0EE7742ACDD457BEA7C7D0931EDB74473045022100CD9A87890ADFAC49B8F69EDEC4A0DB99C86667883D7579289B06DAA4B81BF87E02207AC3FEEA518060AB2B538D330614D2594F432901F7C011D7EB92F74383E5340F81144B4E9C06F24296074F7BC48F92A97916C6DC5EA9",
|
||||
"tx_json": {
|
||||
"Account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"Fee": "15000",
|
||||
"Flags": 0,
|
||||
"Sequence": 353,
|
||||
"SetFlag": 3,
|
||||
"SigningPubKey": "03AB40A0490F9B7ED8DF29D246BF2D6269820A0EE7742ACDD457BEA7C7D0931EDB",
|
||||
"TransactionType": "AccountSet",
|
||||
"TxnSignature": "3045022100CD9A87890ADFAC49B8F69EDEC4A0DB99C86667883D7579289B06DAA4B81BF87E02207AC3FEEA518060AB2B538D330614D2594F432901F7C011D7EB92F74383E5340F",
|
||||
"hash": "59025DD6C9848679BA433448A1DD95833F2F4B64B03E214D074C7A5B6E3E3E70"
|
||||
}
|
||||
}
|
||||
}
|
||||
</code></pre>
|
||||
<h2 id="requireauth">RequireAuth</h2>
|
||||
<p>The <code>RequireAuth</code> setting (<code>requireAuthorization</code> in RippleAPI) prevents all counterparties from holding balances issued by an address unless the address has specifically approved an accounting relationship with that counterparty.</p>
|
||||
<p>We recommend always <a href="#enabling-requireauth">enabling <code>RequireAuth</code></a> for operational addresses and standby addresses, and then never approving any accounting relationships. This prevents operational addresses from creating issuances even by accident. This is a purely precautionary measure, and does not stop those addresses from transferring issuances created by the issuing address, as they are intended to do.</p>
|
||||
<p>If you want to use the <a href="#authorized-accounts">Authorized Accounts</a> feature, you must also enable <code>RequireAuth</code> on your issuing address. When using Authorized Accounts, your issuing address must <a href="#authorizing-trust-lines">submit a <code>TrustSet</code> transaction to approve each accounting relationship</a> that customers create with your issuing address.</p>
|
||||
<p>You can only enable <code>RequireAuth</code> if the address owns no accounting relationships (trust lines) and no offers in the XRP Ledger, so you must decide whether or not to use it before you start doing business in the XRP Ledger.</p>
|
||||
<h3 id="enabling-requireauth">Enabling RequireAuth</h3>
|
||||
<p>The following is an example of using a locally-hosted <code>rippled</code>'s <a href="reference-rippled.html#submit"><code>submit</code> command</a> to send an AccountSet transaction to enable the RequireAuth flag: (This method works the same way regardless of whether the address is an issuing address, operational address, or standby address.)</p>
|
||||
<p>Request:</p>
|
||||
<pre><code>POST http://localhost:5005/
|
||||
{
|
||||
"method": "submit",
|
||||
"params": [
|
||||
{
|
||||
"secret": "sn3nxiW7v8KXzPzAqzyHXbSSKNuN9",
|
||||
"tx_json": {
|
||||
"Account": "rUpy3eEg8rqjqfUoLeBnZkscbKbFsKXC3v",
|
||||
"Fee": "15000",
|
||||
"Flags": 0,
|
||||
"SetFlag": 2,
|
||||
"TransactionType": "AccountSet"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
</code></pre>
|
||||
<p class="devportal-callout caution"><strong>Caution:</strong> Never submit a secret key to a server you do not control. Do not send a secret key unencrypted over the network.</p>
|
||||
<h3 id="authorizing-trust-lines">Authorizing Trust Lines</h3>
|
||||
<p>If you are using the <a href="#authorized-accounts">Authorized Accounts</a> feature, customers cannot hold balances you issue unless you first authorize their accounting relationships to you in the XRP Ledger.</p>
|
||||
<p>To authorize an accounting relationship, submit a TrustSet transaction from your issuing address, with the user to trust as the <code>issuer</code> of the <code>LimitAmount</code>. Leave the <code>value</code> (the amount to trust them for) as <strong>0</strong>, and enable the <a href="reference-transaction-format.html#trustset-flags">tfSetfAuth</a> flag for the transaction.</p>
|
||||
<p>The following is an example of using a locally-hosted <code>rippled</code>'s <a href="reference-rippled.html#submit"><code>submit</code> command</a> to send a TrustSet transaction authorizing the customer address rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn to hold issuances of USD from the issuing address rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW:</p>
|
||||
<p>Request:</p>
|
||||
<pre><code>POST http://localhost:8088/
|
||||
{
|
||||
"method": "submit",
|
||||
"params": [
|
||||
{
|
||||
"secret": "sn3nxiW7v8KXzPzAqzyHXbSSKNuN9",
|
||||
"tx_json": {
|
||||
"Account": "rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW",
|
||||
"Fee": "15000",
|
||||
"TransactionType": "TrustSet",
|
||||
"LimitAmount": {
|
||||
"currency": "USD",
|
||||
"issuer": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"value": 0
|
||||
},
|
||||
"Flags": 65536
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
</code></pre>
|
||||
<p class="devportal-callout caution"><strong>Caution:</strong> Never submit a secret key to a server you do not control. Do not send a secret key unencrypted over the network.</p>
|
||||
<h2 id="robustly-monitoring-for-payments">Robustly Monitoring for Payments</h2>
|
||||
<p>To robustly check for incoming payments, gateways should do the following:</p>
|
||||
<ul>
|
||||
<li>Keep a record of the most-recently-processed transaction and ledger. That way, if you temporarily lose connectivity, you know how far to go back.</li>
|
||||
<li>Check the result code of every incoming payment. Some payments go into the ledger to charge an anti-spam fee, even though they failed. Only transactions with the result code <code>tesSUCCESS</code> can change non-XRP balances. Only transactions from a validated ledger are final.</li>
|
||||
<li><a href="https://ripple.com/files/GB-2014-06.pdf" title="Partial Payment Flag Gateway Bulletin">Look out for Partial Payments</a>. Payments with the partial-payment flag enabled can be considered "successful" if any non-zero amount is delivered, even miniscule amounts.<ul>
|
||||
<li>In <code>rippled</code>, check the transaction for a <code>meta.delivered_amount</code> field. If present, that field indicates how much money <em>actually</em> got delivered to the <code>Destination</code> address.</li>
|
||||
<li>In RippleAPI, you can search the <code>outcome.BalanceChanges</code> field to see how much the destination address received. In some cases, this can be divided into multiple parts on different trust lines.</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>Some transactions change your balances without being payments directly to or from one of your addresses. For example, if ACME sets a nonzero <a href="#transferrate">TransferRate</a>, then ACME's issuing address's outstanding obligations decrease each time Bob and Charlie exchange ACME issuances. See <a href="#transferrate">TransferRate</a> for more information.</li>
|
||||
</ul>
|
||||
<p>To make things simpler for your customers, we recommend accepting payments to either operational addresses and issuing addresses.</p>
|
||||
<p>As an added precaution, we recommend comparing the balances of your issuing address with the collateral funds in your internal accounting system as of each new XRP Ledger ledger version. The issuing address's negative balances should match the assets you have allocated to XRP Ledger outside the network. If the two do not match up, then you should suspend processing payments into and out of the XRP Ledger until you have resolved the discrepancy.</p>
|
||||
<ul>
|
||||
<li>Use <a href="reference-rippled.html#gateway-balances"><code>rippled</code>'s <code>gateway_balances</code> command</a> or <a href="reference-rippleapi.html#gettrustlines">RippleAPI's <code>getTrustlines</code> method</a> to check your balances.</li>
|
||||
<li>If you have a <a href="#transferrate">TransferRate</a> set, then your obligations within the XRP Ledger decrease slightly whenever other XRP Ledger addresses transfer your issuances among themselves.</li>
|
||||
</ul>
|
||||
<h2 id="transferrate">TransferRate</h2>
|
||||
<p>The <em>TransferRate</em> setting (<code>transferRate</code> in RippleAPI) defines a fee to charge for transferring issuances from one XRP Ledger address to another. See <a href="concept-transfer-fees.html">Transfer Fees</a> for more information.</p>
|
||||
<p>The following is an example of using a locally-hosted <code>rippled</code>'s <a href="reference-rippled.html#submit"><code>submit</code> command</a> to send an AccountSet transaction for the issuing address rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW, setting the TransferRate to charge a fee of 0.5%.</p>
|
||||
<p>Request:</p>
|
||||
<pre><code>
|
||||
{
|
||||
"method": "submit",
|
||||
"params": [
|
||||
{
|
||||
"secret": "sn3nxiW7v8KXzPzAqzyHXbSSKNuN9",
|
||||
"tx_json": {
|
||||
"Account": "rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW",
|
||||
"Fee": "10000",
|
||||
"Flags": 0,
|
||||
"TransferRate": 1005000000,
|
||||
"TransactionType": "AccountSet"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
</code></pre>
|
||||
<p>Response:</p>
|
||||
<pre><code>{
|
||||
"result": {
|
||||
"engine_result": "tesSUCCESS",
|
||||
"engine_result_code": 0,
|
||||
"engine_result_message": "The transaction was applied. Only final in a validated ledger.",
|
||||
"status": "success",
|
||||
"tx_blob": "1200032200000000240000000F2B3BE71540684000000000002710732102B3EC4E5DD96029A647CFA20DA07FE1F85296505552CCAC114087E66B46BD77DF74473045022100AAFC3360BE151299523A93F445D5F6EB58AF5A4F8586C8B7818D6C6069660B40022022F46BCDA8FEE256AEB0BA2E92947EF4571F92354AB703E3E6D77FEF7ECBF64E8114204288D2E47F8EF6C99BCC457966320D12409711",
|
||||
"tx_json": {
|
||||
"Account": "rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW",
|
||||
"Fee": "10000",
|
||||
"Flags": 0,
|
||||
"Sequence": 15,
|
||||
"SigningPubKey": "02B3EC4E5DD96029A647CFA20DA07FE1F85296505552CCAC114087E66B46BD77DF",
|
||||
"TransactionType": "AccountSet",
|
||||
"TransferRate": 1005000000,
|
||||
"TxnSignature": "3045022100AAFC3360BE151299523A93F445D5F6EB58AF5A4F8586C8B7818D6C6069660B40022022F46BCDA8FEE256AEB0BA2E92947EF4571F92354AB703E3E6D77FEF7ECBF64E",
|
||||
"hash": "24360352FBF5597F313E5985C1766BB4A0D277CE63219AC0C0D81014C1E663BB"
|
||||
}
|
||||
}
|
||||
}
|
||||
</code></pre>
|
||||
<h3 id="transferrate-with-operational-and-standby-addresses">TransferRate with Operational and Standby Addresses</h3>
|
||||
<p>All XRP Ledger addresses, including operational and standby addresses, are subject to the transfer fee. If you set a nonzero transfer fee, then you must send extra (to pay the TransferRate) when making payments from your operational address or standby address. In other words, your addresses must pay back a little of the balance your issuing address created, each time you make a payment.</p>
|
||||
<ul>
|
||||
<li>In <code>rippled</code>'s APIs, you should set the <a href="reference-transaction-format.html#payment"><code>SendMax</code> transaction parameter</a> higher than the destination <code>Amount</code> parameter.</li>
|
||||
<li>In RippleAPI, you should set the <code>source.maxAmount</code> parameter higher than the <code>destination.amount</code> parameter; or, set the <code>source.amount</code> parameter higher than the <code>destination.minAmount</code> parameter.</li>
|
||||
</ul>
|
||||
<p class="devportal-callout note"><strong>Note:</strong> The TransferRate does not apply when sending issuances directly to the issuing address. The issuing address must always accept its issuances at face value in the XRP Ledger. This means that customers don't have to pay the TransferRate if they send payments to the issuing address directly, but they do when sending to an operational address. If you accept payments at both addresses, you may want to adjust the amount you credit customers in your system of record when customers send payments to the operational address, to compensate for the TransferRate the customer pays.</p>
|
||||
<p>For example: If ACME sets a transfer fee of 1%, an XRP Ledger payment to deliver 5 EUR.ACME from a customer address to ACME's issuing address would cost exactly 5 EUR.ACME. However, the customer would need to send 5.05 EUR.ACME to deliver 5 EUR.ACME to ACME's operational address. (The issuing address's total obligations in the XRP Ledger decrease by 0.05 EUR.ACME.) When ACME credits customers for payments to ACME's operational address, ACME credits the customer for the amount delivered to the operational address <em>and</em> the transfer fee, giving the customer €5,05 in ACME's systems.</p>
|
||||
<h2 id="sending-payments-to-customers">Sending Payments to Customers</h2>
|
||||
<p>When you build an automated system to send payments into the XRP Ledger for your customers, you must make sure that it constructs payments carefully. Malicious actors are constantly trying to find ways to trick a system into paying them more money than it should.</p>
|
||||
<p>One common pitfall is performing pathfinding before sending sending a payment to customers in the XRP Ledger. If you specify the issuers correctly, the <a href="concept-paths.html#default-paths">default paths</a> can deliver the currency as intended.</p>
|
||||
<p>The following is an example of using a locally-hosted <code>rippled</code>'s <a href="reference-rippled.html#submit"><code>submit</code> command</a> to send a payment from the operational address rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn to the customer address raKEEVSGnKSD9Zyvxu4z6Pqpm4ABH8FS6n, sending and delivering funds issued by the issuing address rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW.</p>
|
||||
<p>Request:</p>
|
||||
<pre><code>{
|
||||
"method": "submit",
|
||||
"params": [{
|
||||
"secret": "sn3nxiW7v8KXzPzAqzyHXbSSKNuN9",
|
||||
"tx_json": {
|
||||
"TransactionType": "Payment",
|
||||
"Account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"Destination": "raKEEVSGnKSD9Zyvxu4z6Pqpm4ABH8FS6n",
|
||||
"Amount": {
|
||||
"currency": "USD",
|
||||
"value": "0.13",
|
||||
"issuer": "rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW"
|
||||
},
|
||||
"SendMax": {
|
||||
"currency": "USD",
|
||||
"value": "0.13065",
|
||||
"issuer": "rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW"
|
||||
},
|
||||
"Fee": "10000"
|
||||
}
|
||||
}]
|
||||
}
|
||||
</code></pre>
|
||||
<p><em>Reminder: Don't send your secret to a server you do not control.</em></p>
|
||||
<p>Response:</p>
|
||||
<pre><code>{
|
||||
"result": {
|
||||
"engine_result": "tesSUCCESS",
|
||||
"engine_result_code": 0,
|
||||
"engine_result_message": "The transaction was applied. Only final in a validated ledger.",
|
||||
"status": "success",
|
||||
"tx_blob": "1200002280000000240000016561D4449E57D63540000000000000000000000000005553440000000000204288D2E47F8EF6C99BCC457966320D1240971168400000000000271069D444A4413C6628000000000000000000000000005553440000000000204288D2E47F8EF6C99BCC457966320D12409711732103AB40A0490F9B7ED8DF29D246BF2D6269820A0EE7742ACDD457BEA7C7D0931EDB7446304402207B75D91DC0EEE613A94E05FD5D031568D8A763E99697FF6328745BD226DA7D4E022005C75D7215FD62CB8E46C55B29FCA8E3FC62FDC55DF300597089DD29863BD3CD81144B4E9C06F24296074F7BC48F92A97916C6DC5EA983143A4C02EA95AD6AC3BED92FA036E0BBFB712C030C",
|
||||
"tx_json": {
|
||||
"Account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"Amount": {
|
||||
"currency": "USD",
|
||||
"issuer": "rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW",
|
||||
"value": "0.13"
|
||||
},
|
||||
"Destination": "raKEEVSGnKSD9Zyvxu4z6Pqpm4ABH8FS6n",
|
||||
"Fee": "10000",
|
||||
"Flags": 2147483648,
|
||||
"SendMax": {
|
||||
"currency": "USD",
|
||||
"issuer": "rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW",
|
||||
"value": "0.13065"
|
||||
},
|
||||
"Sequence": 357,
|
||||
"SigningPubKey": "03AB40A0490F9B7ED8DF29D246BF2D6269820A0EE7742ACDD457BEA7C7D0931EDB",
|
||||
"TransactionType": "Payment",
|
||||
"TxnSignature": "304402207B75D91DC0EEE613A94E05FD5D031568D8A763E99697FF6328745BD226DA7D4E022005C75D7215FD62CB8E46C55B29FCA8E3FC62FDC55DF300597089DD29863BD3CD",
|
||||
"hash": "37B4AA5C77A8EB889164CA012E6F064A46B6B7B51677003FC3617F614608C60B"
|
||||
}
|
||||
}
|
||||
}
|
||||
</code></pre>
|
||||
<p>In particular, note the following features of the <a href="reference-transaction-format.html#payment">Payment Transaction</a>:</p>
|
||||
<ul>
|
||||
<li>No <code>Paths</code> field. The payment only succeeds if it can use a <a href="concept-paths.html#default-paths">default path</a>, which is preferable. Using less direct paths can become much more expensive.</li>
|
||||
<li>The <code>issuer</code> of both the <code>SendMax</code> and the <code>Amount</code> is the issuing address. This ensures that the transaction sends and delivers issuances from the issuing address, and not from some other gateway.</li>
|
||||
<li>The <code>value</code> of the <code>SendMax</code> amount is slightly higher than the destination <code>Amount</code>, to compensate for the <a href="#transferrate">transfer fee</a>. In this case, the transfer fee is 0.5%, so the <code>SendMax</code> amount is exactly 1.005 times the destination <code>Amount</code>.</li>
|
||||
</ul>
|
||||
<h2 id="bouncing-payments">Bouncing Payments</h2>
|
||||
<p>When one of your addresses receives a payment whose purpose is unclear, we recommend that you try to return the money to its sender. While this is more work than pocketing the money, it demonstrates good faith towards customers. You can have an operator bounce payments manually, or create a system to do so automatically.</p>
|
||||
<p>The first requirement to bouncing payments is <a href="#robustly-monitoring-for-payments">robustly monitoring for incoming payments</a>. You do not want to accidentally refund a customer for more than they sent you! (This is particularly important if your bounce process is automated.) The <a href="https://ripple.com/files/GB-2014-06.pdf">Partial Payment Flag Gateway Bulletin (PDF)</a> explains how to avoid a common problem.</p>
|
||||
<p>Second, you should send bounced payments as Partial Payments. Since third parties can manipulate the cost of pathways between addresses, Partial Payments allow you to divest yourself of the full amount without being concerned about exchange rates within the XRP Ledger. You should publicize your bounced payments policy as part of your terms of use. Send the bounced payment from either an operational address or a standby address.</p>
|
||||
<ul>
|
||||
<li>To send a Partial Payment using <code>rippled</code>, enable the <a href="reference-transaction-format.html#payment-flags">tfPartialPayment flag</a> on the transaction. Set the <code>Amount</code> field to the amount you received and omit the <code>SendMax</code> field.</li>
|
||||
<li>To send a Partial Payment using RippleAPI, set the <code>allowPartialPayment</code> field of the <a href="reference-rippleapi.html#payment">Payment object</a> to <code>true</code>. Set the <code>source.maxAmount</code> and <code>destination.amount</code> both equal to the amount you received.</li>
|
||||
</ul>
|
||||
<p>You should use the <code>SourceTag</code> value (<code>source.tag</code> in RippleAPI) from the incoming payment as the <code>DestinationTag</code> value (<code>destination.tag</code> in RippleAPI) for the return payment.</p>
|
||||
<p>To prevent two systems from bouncing payments back and forth indefinitely, you can set a new Source Tag for the outgoing return payment. If you receive an unexpected payment whose Destination Tag matches the Source Tag of a return you sent, then do not bounce it back again.</p>
|
||||
<h2 id="reliable-transaction-submission">Reliable Transaction Submission</h2>
|
||||
<p>The goal of reliably submitting transactions is to achieve the following two properties in a finite amount of time:</p>
|
||||
<ul>
|
||||
<li>Idempotency - Transactions should be processed once and only once, or not at all.</li>
|
||||
<li>Verifiability - Applications can determine the final result of a transaction.</li>
|
||||
</ul>
|
||||
<p>To submit transactions reliably, follow these guidelines:</p>
|
||||
<ul>
|
||||
<li>Persist details of the transaction before submitting it.</li>
|
||||
<li>Use the <code>LastLedgerSequence</code> parameter. (RippleAPI does this by default.)</li>
|
||||
<li>Resubmit a transaction if it has not appeared in a validated ledger whose sequence number is less than or equal to the transaction's <code>LastLedgerSequence</code> parameter.</li>
|
||||
</ul>
|
||||
<p>For more information, see <a href="tutorial-reliable-transaction-submission.html">Reliable Transaction Submission</a>.</p>
|
||||
<h2 id="rippletxt">ripple.txt</h2>
|
||||
<p>The <a href="https://wiki.ripple.com/Ripple.txt">ripple.txt</a> standard provides a way to publish information about your gateway so that automated tools and applications can read and understand it.</p>
|
||||
<p>For example, if you run a validating <code>rippled</code> server, you can use ripple.txt to publish the public key of your validating server. You can also publish information about what currencies your gateway issues, and which XRP Ledger addresses you control, to protect against impostors or confusion.</p>
|
||||
<!-- STYLE_OVERRIDE: gateway, gateways -->
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<footer class="content-info" role="contentinfo">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-sm-12 absolute_bottom_footer">
|
||||
<div class="col-sm-8">
|
||||
<span>© 2013 - 2017 Ripple Labs, Inc. All Rights Reserved.</span>
|
||||
<span><a href="/terms-of-use/">Terms</a></span>
|
||||
<span><a href="/privacy-policy/">Privacy</a></span>
|
||||
</div>
|
||||
</div><!-- /.absolute_bottom_footer -->
|
||||
|
||||
</div><!-- /.row -->
|
||||
</div><!-- /.container -->
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,776 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<meta name="viewport" content="width=device-width">
|
||||
|
||||
<title>Listing XRP as an Exchange - Ripple Developer Portal</title>
|
||||
|
||||
<!-- favicon -->
|
||||
<link rel="icon" href="favicon.ico" type="image/x-icon">
|
||||
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon">
|
||||
|
||||
<!-- jQuery -->
|
||||
<script src="assets/vendor/jquery-1.11.1.min.js"></script>
|
||||
|
||||
<!-- Custom Stylesheets. ripple.css includes bootstrap, font stuff -->
|
||||
<link href="assets/css/ripple.css" rel="stylesheet" />
|
||||
<link href="assets/css/devportal.css" rel="stylesheet" />
|
||||
|
||||
<!-- Bootstrap JS -->
|
||||
<script src="assets/vendor/bootstrap.min.js"></script>
|
||||
|
||||
|
||||
<!-- syntax highlighting -->
|
||||
<link rel="stylesheet" href="assets/vendor/docco.min.css" />
|
||||
<script src="assets/vendor/highlight.min.js"></script>
|
||||
|
||||
<!-- syntax selection js -->
|
||||
<script src="assets/js/multicodetab.js"></script>
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
$(".multicode").minitabs();
|
||||
hljs.initHighlighting();
|
||||
make_code_expandable();
|
||||
});
|
||||
</script>
|
||||
|
||||
<script src="assets/js/expandcode.js"></script>
|
||||
<script src="assets/js/fixsidebarscroll.js"></script>
|
||||
|
||||
<!-- fontawesome icons -->
|
||||
<link rel="stylesheet" href="assets/vendor/fontawesome/css/font-awesome.min.css" />
|
||||
|
||||
</head>
|
||||
|
||||
<body class="page page-template page-template-template-dev-portal page-template-template-dev-portal-php sidebar-primary wpb-js-composer js-comp-ver-3.6.2 vc_responsive">
|
||||
<header role="banner" class="banner navbar navbar-default navbar-fixed-top initial_header">
|
||||
<div class="container">
|
||||
<div class="navbar-header">
|
||||
<a href="index.html" class="navbar-brand"><img src="assets/img/ripple-logo-color.png" class="logo"></a>
|
||||
</div><!-- /.navbar-header -->
|
||||
<div class="nav">
|
||||
<div class="draft-warning">DRAFT PAGE</div>
|
||||
</div><!-- /.nav -->
|
||||
|
||||
</div><!-- /.container -->
|
||||
|
||||
<div class="subnav dev_nav">
|
||||
<div class="container">
|
||||
<ul id="menu-dev-menu" class="menu">
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">References <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="reference-rippleapi.html">RippleAPI</a></li>
|
||||
<li><a href="reference-rippled.html">rippled</a></li>
|
||||
<li><a href="reference-transaction-format.html">Transaction Format</a></li>
|
||||
<li><a href="reference-ledger-format.html">Ledger Format</a></li>
|
||||
<li><a href="reference-data-api.html">Ripple Data API v2</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorials <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="tutorial-multisign.html">How to Multi-Sign</a></li>
|
||||
<li><a href="tutorial-paychan.html">Payment Channels Tutorial</a></li>
|
||||
<li><a href="concept-issuing-and-operational-addresses.html">Issuing and Operational Addresses</a></li>
|
||||
<li><a href="tutorial-reliable-transaction-submission.html">Reliable Transaction Submission</a></li>
|
||||
<li><a href="tutorial-rippleapi-beginners-guide.html">RippleAPI Beginners Guide</a></li>
|
||||
<li><a href="tutorial-rippled-setup.html">rippled Setup</a></li>
|
||||
<li><a href="tutorial-gateway-guide.html">Gateway Guide</a></li>
|
||||
<li><a href="tutorial-listing-xrp.html">Listing XRP as an Exchange</a></li>
|
||||
<li><a href="tutorial-escrow.html">Escrow Tutorials</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Features <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="concept-accounts.html">Accounts</a></li>
|
||||
<li><a href="concept-amendments.html">Amendments</a></li>
|
||||
<li><a href="concept-consensus.html">Consensus Process</a></li>
|
||||
<li><a href="concept-reaching-consensus.html">Reaching Consensus in the XRP Ledger</a></li>
|
||||
<li><a href="concept-fee-voting.html">Fee Voting</a></li>
|
||||
<li><a href="concept-fees.html">Fees (Disambiguation)</a></li>
|
||||
<li><a href="concept-freeze.html">Freeze</a></li>
|
||||
<li><a href="concept-partial-payments.html">Partial Payments</a></li>
|
||||
<li><a href="concept-paths.html">Paths</a></li>
|
||||
<li><a href="concept-reserves.html">Reserves</a></li>
|
||||
<li><a href="concept-stand-alone-mode.html">Stand-Alone Mode</a></li>
|
||||
<li><a href="concept-transaction-cost.html">Transaction Cost</a></li>
|
||||
<li><a href="concept-transfer-fees.html">Transfer Fees</a></li>
|
||||
<li><a href="concept-noripple.html">Understanding the NoRipple flag</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Gateway Bulletins <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="gb-2015-06.html">GB-2015-06: Corrections to Autobridging</a></li>
|
||||
<li><a href="gb-2015-05.html">GB-2015-05: Historical Ledger Query Migration</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">API Tools <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="ripple-api-tool.html">WebSocket API Tool</a></li>
|
||||
<li><a href="data-api-v2-tool.html">Data API v2 Tool</a></li>
|
||||
<li><a href="tool-jsonrpc.html">rippled JSON-RPC Tool</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li><a href="https://github.com/ripple/ripple-dev-portal" title="GitHub">Site Source</a></li>
|
||||
</ul><!-- /#dev-menu -->
|
||||
</div><!-- /.subnav .container -->
|
||||
</div><!-- /.subnav -->
|
||||
</header>
|
||||
|
||||
|
||||
<div class="wrap container" role="document">
|
||||
<aside class="sidebar" role="complementary">
|
||||
<div class="dev_nav_wrapper">
|
||||
<div id="cont">
|
||||
<h5>In this category:</h5>
|
||||
<ul class="dev_nav_sidebar">
|
||||
<li class="level-1"><a href="index.html">Category: Tutorials</a></li>
|
||||
<li class="level-2"><a href="tutorial-multisign.html">How to Multi-Sign</a></li>
|
||||
<li class="level-2"><a href="tutorial-paychan.html">Payment Channels Tutorial</a></li>
|
||||
<li class="level-2"><a href="concept-issuing-and-operational-addresses.html">Issuing and Operational Addresses</a></li>
|
||||
<li class="level-2"><a href="tutorial-reliable-transaction-submission.html">Reliable Transaction Submission</a></li>
|
||||
<li class="level-2"><a href="tutorial-rippleapi-beginners-guide.html">RippleAPI Beginners Guide</a></li>
|
||||
<li class="level-2"><a href="tutorial-rippled-setup.html">rippled Setup</a></li>
|
||||
<li class="level-2"><a href="tutorial-gateway-guide.html">Gateway Guide</a></li>
|
||||
<li class="level-2"><a href="tutorial-listing-xrp.html">Listing XRP as an Exchange</a></li>
|
||||
<li class="level-2"><a href="tutorial-escrow.html">Escrow Tutorials</a></li>
|
||||
</ul>
|
||||
<hr />
|
||||
<h5>In this page:</h5>
|
||||
<ul class="dev_nav_sidebar" id="dactyl_toc_sidebar">
|
||||
<li class="level-1"><a href="#listing-xrp-as-an-exchange">Listing XRP as an Exchange</a></li>
|
||||
<li class="level-2"><a href="#alpha-exchange">Alpha Exchange</a></li>
|
||||
<li class="level-3"><a href="#user-benefits">User Benefits</a></li>
|
||||
<li class="level-2"><a href="#prerequisites-for-supporting-xrp">Prerequisites for Supporting XRP</a></li>
|
||||
<li class="level-3"><a href="#partial-payments">Partial Payments</a></li>
|
||||
<li class="level-3"><a href="#accounts">Accounts</a></li>
|
||||
<li class="level-3"><a href="#balance-sheets">Balance Sheets</a></li>
|
||||
<li class="level-2"><a href="#flow-of-funds">Flow of Funds</a></li>
|
||||
<li class="level-3"><a href="#deposit-xrp-into-exchange">Deposit XRP into Exchange</a></li>
|
||||
<li class="level-3"><a href="#trade-xrp-on-the-exchange">Trade XRP on the Exchange</a></li>
|
||||
<li class="level-3"><a href="#rebalance-xrp-holdings">Rebalance XRP Holdings</a></li>
|
||||
<li class="level-3"><a href="#withdraw-xrp-from-exchange">Withdraw XRP from Exchange</a></li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
<main class="main" role="main">
|
||||
<div class='content'>
|
||||
<h1 id="listing-xrp-as-an-exchange">Listing XRP as an Exchange</h1>
|
||||
<p>This document describes the steps that an exchange needs to take to list XRP. For details about other aspects of <code>rippled</code> and the XRP Ledger, see the <a href="https://ripple.com/build">Ripple Developer Center</a>.</p>
|
||||
<h2 id="alpha-exchange">Alpha Exchange</h2>
|
||||
<p>For illustrative purposes, this document uses a fictitious business called <em>Alpha Exchange</em> to explain the high-level steps required to list XRP. For the purposes of this document, Alpha Exchange:</p>
|
||||
<ul>
|
||||
<li>
|
||||
<p>Currently specializes in listing BTC/USD</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Wants to add BTC/XRP and XRP/USD trading pairs</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Maintains balances for all of its customers</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Maintains balances for each of its supported currencies</p>
|
||||
</li>
|
||||
</ul>
|
||||
<h3 id="user-benefits">User Benefits</h3>
|
||||
<p>Alpha Exchange wants to list BTC/XRP and XRP/USD trading pairs partially because listing these pairs will benefit its users. Specifically, this support will allow its users to:</p>
|
||||
<ul>
|
||||
<li>
|
||||
<p>Deposit XRP <em>to</em> Alpha Exchange <em>from</em> the XRP Ledger</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Withdraw XRP <em>from</em> Alpha Exchange <em>to</em> the XRP Ledger</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Trade XRP with other currencies, such as BTC, USD, among others</p>
|
||||
</li>
|
||||
</ul>
|
||||
<h2 id="prerequisites-for-supporting-xrp">Prerequisites for Supporting XRP</h2>
|
||||
<p>To support XRP, Alpha Exchange must:</p>
|
||||
<ul>
|
||||
<li>
|
||||
<p>Create and maintain new <a href="#accounts">accounts</a></p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Create and maintain <a href="#balance-sheets">balance sheets</a></p>
|
||||
</li>
|
||||
</ul>
|
||||
<p>See also:</p>
|
||||
<ul>
|
||||
<li>
|
||||
<p><a href="tutorial-gateway-guide.html#gateway-compliance">Gateway Compliance</a> — Gateways and exchanges are different, but exchanges should also ensure that they are complying with local regulations and reporting to the appropriate agencies.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><a href="tutorial-gateway-guide.html#requirements-for-sending-to-xrp-ledger">Requirements for Sending to XRP Ledger</a></p>
|
||||
</li>
|
||||
<li>
|
||||
<p><a href="tutorial-gateway-guide.html#requirements-for-receiving-from-xrp-ledger">Requirements for Receiving from XRP Ledger</a></p>
|
||||
</li>
|
||||
<li>
|
||||
<p><a href="tutorial-gateway-guide.html#precautions">Gateway Precautions</a></p>
|
||||
</li>
|
||||
</ul>
|
||||
<h3 id="partial-payments">Partial Payments</h3>
|
||||
<p>Before integrating, exchanges should be aware of the <a href="reference-transaction-format.html#partial-payments">partial payments</a> feature. This feature allows XRP Ledger users to send successful payments that reduce the amount received instead of increasing the <code>SendMax</code>. This feature can be useful for <a href="tutorial-gateway-guide.html#bouncing-payments">returning payments</a> without incurring additional cost as the sender.</p>
|
||||
<h4 id="partial-payments-warning">Partial Payments Warning</h4>
|
||||
<p>When the <a href="reference-transaction-format.html#payment-flags">tfPartialPayment flag</a> is enabled, the <code>Amount</code> field <strong><em>is not guaranteed to be the amount received</em></strong>. The <code>delivered_amount</code> field of a payment's metadata indicates the amount of currency actually received by the destination account. When receiving a payment, use <code>delivered_amount</code> instead of the Amount field to determine how much your account received instead.</p>
|
||||
<p class="devportal-callout warning"><strong>Warning:</strong> Be aware that malicious actors could exploit this. For more information, see <a href="concept-partial-payments.html">Partial Payments</a>.</p>
|
||||
<h3 id="accounts">Accounts</h3>
|
||||
<p>XRP is held in <em>accounts</em> (also referred to as <em>wallets</em> or <em>addresses</em> ) on the XRP Ledger. Accounts on the XRP Ledger are different than accounts on other blockchain ledgers, such as Bitcoin, where accounts incur little to no overhead. In the XRP Ledger, accounts can <a href="concept-accounts.html#permanence-of-accounts">never be deleted</a>, and each account must hold a separate <a href="concept-reserves.html">reserve of XRP</a> that cannot be sent to others. For these reasons, Ripple recommends that institutions not create excessive or needless accounts.</p>
|
||||
<p>To comply with Ripple's recommended best practices, Alpha Exchange should create at least two new accounts on the XRP Ledger. To minimize the risks associated with a compromised secret key, Ripple recommends creating <a href="https://ripple.com/build/issuing-operational-addresses/"><em>cold</em>, <em>hot</em>, and <em>warm</em> accounts</a> (these are sometimes referred to, respectively, as cold, hot, and warm wallets). The hot/warm/cold model is intended to balance security and convenience. Exchanges listing XRP should create the following accounts:</p>
|
||||
<ul>
|
||||
<li>
|
||||
<p>A <a href="concept-issuing-and-operational-addresses.html#issuing-address"><em>cold wallet</em></a> to securely hold the majority of XRP and customers' funds. For exchanges, this is also the address to which its users send <a href="#deposit-xrp-into-exchange">deposits</a>. To provide optimal security, this account's secret key should be offline.</p>
|
||||
<p>If a malicious actor compromises an exchange's cold wallet, the possible consequences are:</p>
|
||||
<ul>
|
||||
<li>
|
||||
<p>The malicious actor gets full access to all XRP in the cold wallet.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>If the master key is compromised, the malicious actor can irrevocably take control of the cold wallet forever (by disabling the master key and setting a new regular key or signer list). This would also give the malicious actor control over all future XRP received by the cold wallet.</p>
|
||||
<ul>
|
||||
<li>If this happens, the exchange has to make a new cold wallet address and tell its customers the new address.</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<p>If the regular key or signer list are comromised, the exchange can regain control of the cold wallet. However, some of a malicious actor's actions cannot easily be undone:</p>
|
||||
<ul>
|
||||
<li>
|
||||
<p>The malicious actor could issue currency in the XRP Ledger by using the cold wallet, but that currency should not be valued by anyone (unless the exchange explicitly stated it was also a gateway).</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>If a malicious actor sets the asfRequireAuth flag for the account, that cannot be unset, although this only relates issuing currency and therefore should not affect an exchange that's not also a gateway. Any other settings a malicious actor sets or unsets with a master key can be reverted.</p>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<p>One or more <a href="concept-issuing-and-operational-addresses.html#operational-addresses"><em>hot wallets</em></a> to conduct the day-to-day business of managing customers' XRP withdrawals and deposits. For example, with a hot wallet, exchanges can securely support these types of automated XRP transfers. Hot wallets need to be online to service instant withdrawal requests.</p>
|
||||
<p>For more information about the possible consequences of a compromised hot wallet, see <a href="concept-issuing-and-operational-addresses.html#operational-address-compromise">Operational Account Compromise</a>.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Optionally, one or more warm wallets to provide an additional layer of security between the cold and hot wallets. Unlike a hot wallet, the secret key of a warm wallet does not need to be online. Additionally, you can distribute the secret keys for the warm wallet to several different people and implement <a href="tutorial-multisign.html">multisigning</a> to increase security.</p>
|
||||
<p>For more information about the possible consequences of a compromised warm wallet, see <a href="concept-issuing-and-operational-addresses.html#standby-address-compromise">Standby Account Compromise</a>.</p>
|
||||
</li>
|
||||
</ul>
|
||||
<p>See also:</p>
|
||||
<ul>
|
||||
<li>
|
||||
<p><a href="tutorial-gateway-guide.html#suggested-business-practices">"Suggested Business Practices" in the <em>Gateway Guide</em></a></p>
|
||||
</li>
|
||||
<li>
|
||||
<p><a href="concept-issuing-and-operational-addresses.html">Issuing and Operational Addresses</a></p>
|
||||
</li>
|
||||
<li>
|
||||
<p><a href="reference-transaction-format.html#creating-accounts">Creating Accounts</a></p>
|
||||
</li>
|
||||
<li>
|
||||
<p><a href="concept-reserves.html">Reserves</a></p>
|
||||
</li>
|
||||
</ul>
|
||||
<h3 id="balance-sheets">Balance Sheets</h3>
|
||||
<p>To custody its ccustomers' XRP, Alpha Exchange must track each customer's XRP balance and its own holdings. To do this, Alpha Exchange must create and maintain an additional balance sheet or accounting system. The following table illustrates what this balance sheet might look like.</p>
|
||||
<p>The new XRP Ledger accounts (<em>Alpha Hot</em>, <em>Alpha Warm</em>, <em>Alpha Cold</em>) are in the <em>User</em> column of the <em>XRP Balances on XRP Ledger</em> table.</p>
|
||||
<p>The <em>Alpha Exchange XRP Balances</em> table represents new, additional balance sheet. Alpha Exchange’s software manages their users’ balances of XRP on this accounting system.</p>
|
||||
<table>
|
||||
<tr>
|
||||
<td><b><i>XRP Balances
|
||||
on XRP Ledger</i></b></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td><b><i>Alpha Exchange
|
||||
XRP Balances</i></b></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>User</b></td>
|
||||
<td><b>Balance</b></td>
|
||||
<td></td>
|
||||
<td><b>Acct #</b></td>
|
||||
<td><b>User</b></td>
|
||||
<td><b>Balance</b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Dave</td>
|
||||
<td>25,000</td>
|
||||
<td></td>
|
||||
<td>123</td>
|
||||
<td>Alice</td>
|
||||
<td>0</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Edward</td>
|
||||
<td>45,000</td>
|
||||
<td></td>
|
||||
<td>456</td>
|
||||
<td>Bob</td>
|
||||
<td>0</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Charlie</td>
|
||||
<td>50,000</td>
|
||||
<td></td>
|
||||
<td>789</td>
|
||||
<td>Charlie</td>
|
||||
<td>0</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><i>Alpha Hot</i></td>
|
||||
<td>0</td>
|
||||
<td></td>
|
||||
<td>...</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><i>Alpha Warm</i></td>
|
||||
<td>0</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><i>Alpha Cold</i></td>
|
||||
<td>0</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>...</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</table>
|
||||
<h4 id="xrp-amounts">XRP Amounts</h4>
|
||||
<p>Amounts of XRP are represented on the XRP Ledger as an unsigned integer count of <em>drops</em>, where one XRP is 1,000,000 drops. Ripple recommends that software store XRP balances as integer amounts of drops, and perform integer arithmetic on these values. However, user interfaces should present balances in units of XRP.</p>
|
||||
<p>One drop (.000001 XRP) cannot be further subdivided. Keep this in mind when calculating and displaying FX rates between XRP and other assets.</p>
|
||||
<p>For more information, see <a href="reference-rippled.html#specifying-currency-amounts">Specifying Currency Amounts</a>.</p>
|
||||
<h4 id="on-ledger-and-off-ledger">On-Ledger and Off-Ledger</h4>
|
||||
<p>With exchanges like <em>Alpha Exchange</em>, XRP can be "on-ledger" or "off-ledger":</p>
|
||||
<ul>
|
||||
<li>
|
||||
<p><strong>On-Ledger XRP</strong>: XRP that can be queried through the public XRP Ledger by specifying the public <a href="concept-accounts.html#addresses">address</a> of the XRP holder. The counterparty to these balances is the XRP Ledger. For more information, see <a href="reference-rippled.html#currencies">Currencies</a>.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><strong>Off-Ledger XRP</strong>: XRP that is held by the accounting system of an exchange and can be queried through the exchange interface. Off-ledger XRP balances are credit-based. The counterparty is the exchange holding the XRP.</p>
|
||||
<p>Off-ledger XRP balances are traded between the participants of an exchange. To support these trades, the exchange must hold a balance of <em>on-ledger XRP</em> equal to the aggregate amount of <em>off-ledger XRP</em> that it makes available for trade.</p>
|
||||
</li>
|
||||
</ul>
|
||||
<h2 id="flow-of-funds">Flow of Funds</h2>
|
||||
<p>The remaining sections describe how funds flow through the accounts managed by Alpha Exchange as its users begin to deposit, trade, and redeem XRP balances. To illustrate the flow of funds, this document uses the tables introduced in the <a href="#balance-sheets">"Balance Sheets" section</a>.</p>
|
||||
<p>There are four main steps involved in an exchange's typical flow of funds:</p>
|
||||
<ol>
|
||||
<li>
|
||||
<p><a href="#deposit-xrp-into-exchange">Deposit XRP into Exchange</a></p>
|
||||
</li>
|
||||
<li>
|
||||
<p><a href="#rebalance-xrp-holdings">Rebalance XRP Holdings</a></p>
|
||||
</li>
|
||||
<li>
|
||||
<p><a href="#withdraw-xrp-from-exchange">Withdraw XRP from Exchange</a></p>
|
||||
</li>
|
||||
<li>
|
||||
<p><a href="#trade-xrp-on-the-exchange">Trade XRP on the Exchange</a></p>
|
||||
</li>
|
||||
</ol>
|
||||
<p>This list does not include the <a href="#prerequisites-for-supporting-xrp">prerequisites</a> required of an exchange.</p>
|
||||
<p>At this point, <em>Alpha Exchange</em> has created <a href="#accounts">hot, warm, and cold wallets</a> on the XRP Ledger and added them to its balance sheet, but has not accepted any deposits from its users.</p>
|
||||
<table>
|
||||
<tr>
|
||||
<td><b><i>XRP Balances
|
||||
on XRP Ledger</i></b></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td><b><i>Alpha Exchange
|
||||
XRP Balances</i></b></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>User</b></td>
|
||||
<td><b>Balance</b></td>
|
||||
<td></td>
|
||||
<td><b>Acct #</b></td>
|
||||
<td><b>User</b></td>
|
||||
<td><b>Balance</b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Dave</td>
|
||||
<td>25,000</td>
|
||||
<td></td>
|
||||
<td>123</td>
|
||||
<td>Alice</td>
|
||||
<td>0</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Edward</td>
|
||||
<td>45,000</td>
|
||||
<td></td>
|
||||
<td>456</td>
|
||||
<td>Bob</td>
|
||||
<td>0</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Charlie</td>
|
||||
<td>50,000</td>
|
||||
<td></td>
|
||||
<td>789</td>
|
||||
<td>Charlie</td>
|
||||
<td>0</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><i>Alpha Hot</i></td>
|
||||
<td>0</td>
|
||||
<td></td>
|
||||
<td>...</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><i>Alpha Warm</i></td>
|
||||
<td>0</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><i>Alpha Cold</i></td>
|
||||
<td>0</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>...</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</table>
|
||||
<h3 id="deposit-xrp-into-exchange">Deposit XRP into Exchange</h3>
|
||||
<p>To track <a href="#on-ledger-and-off-ledger">off-ledger XRP balances</a>, exchanges need to create new <a href="#balance-sheets">balance sheets</a> (or similar accounting systems). The following table illustrates the balance changes that take place on Alpha Exchange's new balance sheet as users begin to deposit XRP.</p>
|
||||
<p>A user named Charlie wants to deposit 50,000 XRP to Alpha Exchange. Doing this involves the following steps:</p>
|
||||
<ol>
|
||||
<li>
|
||||
<p>Charlie submits a payment of 50,000 XRP (by using <a href="reference-rippleapi.html">RippleAPI</a> or similar software) to Alpha Exchange's <a href="#accounts">cold wallet</a>.</p>
|
||||
<p>a. Charlie adds an identifier (in this case, <code>789</code>) to the payment to associate it with his account at Alpha Exchange. This is called a <a href="tutorial-gateway-guide.html#source-and-destination-tags"><em>destination tag</em></a>. (To use this, Alpha Exchange should have set the asfRequireDest flag on all of its accounts to require all incoming payments to have a destination tag like Charlie's. For more information, see <a href="reference-transaction-format.html#accountset-flags">AccountSet Flags</a>).</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>The software at Alpha Exchange detects the incoming payment, and recognizes <code>789</code> as the destination tag for Charlie’s account.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>When it detects the incoming payment, Alpha Exchange's software updates its balance sheet to indicate that the 50,000 XRP it received is controlled by Charlie.</p>
|
||||
<p>Charlie can now use up to 50,000 XRP on the exchange. For example, he can create offers to trade XRP with BTC or any of the other currencies Alpha Exchange supports.</p>
|
||||
</li>
|
||||
</ol>
|
||||
<table>
|
||||
<tr>
|
||||
<td><b><i>XRP Balances
|
||||
on XRP Ledger</i></b></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td><b><i>Alpha Exchange
|
||||
XRP Balances</i></b></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>User</b></td>
|
||||
<td><b>Balance</b></td>
|
||||
<td></td>
|
||||
<td><b>Acct #</b></td>
|
||||
<td><b>User</b></td>
|
||||
<td><b>Balance</b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Dave</td>
|
||||
<td>25,000</td>
|
||||
<td></td>
|
||||
<td>123</td>
|
||||
<td>Alice</td>
|
||||
<td>0</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Edward</td>
|
||||
<td>45,000</td>
|
||||
<td></td>
|
||||
<td>456</td>
|
||||
<td>Bob</td>
|
||||
<td>0</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Charlie</td>
|
||||
<td><s>100,000</s>
|
||||
<br/>50,000</td>
|
||||
<td></td>
|
||||
<td>789</td>
|
||||
<td>Charlie</td>
|
||||
<td><s>0</s>
|
||||
<br/>50,000</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Alpha Hot</td>
|
||||
<td>0</td>
|
||||
<td></td>
|
||||
<td>...</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Alpha Warm</td>
|
||||
<td>0</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Alpha Cold</td>
|
||||
<td><s>0</s>
|
||||
<br/>50,000</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>...</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</table>
|
||||
<h3 id="trade-xrp-on-the-exchange">Trade XRP on the Exchange</h3>
|
||||
<p>Alpha Exchange users (like Charlie) can trade credit-based balances on Alpha Exchange. Alpha Exchange should keep track of user balances on its new balance sheet as these trades are made. These trades are <em>off-ledger</em> and independent from the XRP Ledger, so the balance changes are not recorded on the XRP Ledger.</p>
|
||||
<p>Customers who hold XRP in their own XRP Ledger accounts can also use the distributed exchange built into the XRP Ledger to trade currencies issued by gateways. For more information about trading <em>on</em> the XRP Ledger, see <a href="reference-transaction-format.html#lifecycle-of-an-offer">Lifecycle of an Offer</a>.</p>
|
||||
<h3 id="rebalance-xrp-holdings">Rebalance XRP Holdings</h3>
|
||||
<p>Exchanges can adjust the balances between their hot and cold wallets at any time. Each balance adjustment consumes a <a href="concept-transaction-cost.html">transaction cost</a>, but does not otherwise affect the aggregate balance of all the accounts. The aggregate, on-ledger balance should always exceed the total balance available for trade on the exchange. (The excess should be sufficient to cover the XRP Ledger's transaction cost.)</p>
|
||||
<p>The following table demonstrates a balance adjustment of 80,000 XRP (via a <a href="reference-transaction-format.html#payment"><em>payment</em></a> on the XRP Ledger) between Alpha Exchange's cold wallet and its hot wallet, where the cold wallet was debited and the hot wallet was credited. If the payment were reversed (debiting the hot wallet and crediting the cold wallet), the hot wallet balance would decrease. Balance adjustments like these allow an exchange to limit the risks associated with holding XRP in online hot wallets.</p>
|
||||
<table>
|
||||
<tr>
|
||||
<td><b><i>Alpha Exchange XRP
|
||||
Off-Ledger Balances</i></b></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td><b><i>Alpha Exchange XRP On-Ledger Balances</i></b></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Acct #</b></td>
|
||||
<td><b>User</b></td>
|
||||
<td><b>Balance</b></td>
|
||||
<td></td>
|
||||
<td><b>XRP Ledger Account</b></td>
|
||||
<td><b>Balance</b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>123</td>
|
||||
<td>Alice</td>
|
||||
<td>80,000</td>
|
||||
<td></td>
|
||||
<td>Hot</td>
|
||||
<td><s>0</s>
|
||||
<br/>80,000</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>456</td>
|
||||
<td>Bob</td>
|
||||
<td>50,000</td>
|
||||
<td></td>
|
||||
<td>Warm</td>
|
||||
<td>0</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>….</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>….</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>789</td>
|
||||
<td>Charlie</td>
|
||||
<td>50,000</td>
|
||||
<td></td>
|
||||
<td>Cold</td>
|
||||
<td><s>180,000</s>
|
||||
<br/>100,000</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>...</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>...</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</table>
|
||||
<h3 id="withdraw-xrp-from-exchange">Withdraw XRP from Exchange</h3>
|
||||
<p>Withdrawals allow an exchange's users to move XRP from the exchange's off-ledger balance sheet to an account on the XRP Ledger.</p>
|
||||
<p>In this example, Charlie withdraws 25,000 XRP from Alpha Exchange. This involves the following steps:</p>
|
||||
<ol>
|
||||
<li>
|
||||
<p>Charlie initiates the process on Alpha Exchange’s website. He provides instructions to transfer 25,000 XRP to a specific account on the XRP Ledger (named "Charlie XRP Ledger" in the following table).</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>In response to Charlie’s instructions, Alpha Exchange does the following:</p>
|
||||
<p>a. Debits the amount (25,000 XRP) from Charlie’s account on its off-ledger balance sheet</p>
|
||||
<p>b. Submits a payment on the XRP Ledger for the same amount (25,000 XRP), from Alpha Exchange's hot wallet to Charlie’s XRP Ledger account</p>
|
||||
</li>
|
||||
</ol>
|
||||
<table>
|
||||
<tr>
|
||||
<td><b><i>XRP Ledger On-Ledger XRP Balances</i></b></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td><b><i>Alpha Exchange XRP
|
||||
Off-Ledger Balances</i></b></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td><b><i>Alpha Exchange XRP On-Ledger Balances</i></b></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>User</b></td>
|
||||
<td><b>Balance</b></td>
|
||||
<td></td>
|
||||
<td><b>Acct #</b></td>
|
||||
<td><b>User</b></td>
|
||||
<td><b>Balance</b></td>
|
||||
<td></td>
|
||||
<td><b>XRP Ledger Account</b></td>
|
||||
<td><b>Balance</b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Dave</td>
|
||||
<td>25,000</td>
|
||||
<td></td>
|
||||
<td>123</td>
|
||||
<td>Alice</td>
|
||||
<td>80,000</td>
|
||||
<td></td>
|
||||
<td>Hot</td>
|
||||
<td><s>80,000</s>
|
||||
<br/>55,000</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Edward</td>
|
||||
<td>45,000</td>
|
||||
<td></td>
|
||||
<td>456</td>
|
||||
<td>Bob</td>
|
||||
<td>50,000</td>
|
||||
<td></td>
|
||||
<td>Warm</td>
|
||||
<td>0</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>….</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>….</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>….</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Charlie XRP Ledger</td>
|
||||
<td><s>50,000</s>
|
||||
<br/>75,000</td>
|
||||
<td></td>
|
||||
<td>789</td>
|
||||
<td>Charlie</td>
|
||||
<td><s>50,000</s>
|
||||
<br/>25,000</td>
|
||||
<td></td>
|
||||
<td>Cold</td>
|
||||
<td>100,000</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>...</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>...</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>...</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<footer class="content-info" role="contentinfo">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-sm-12 absolute_bottom_footer">
|
||||
<div class="col-sm-8">
|
||||
<span>© 2013 - 2017 Ripple Labs, Inc. All Rights Reserved.</span>
|
||||
<span><a href="/terms-of-use/">Terms</a></span>
|
||||
<span><a href="/privacy-policy/">Privacy</a></span>
|
||||
</div>
|
||||
</div><!-- /.absolute_bottom_footer -->
|
||||
|
||||
</div><!-- /.row -->
|
||||
</div><!-- /.container -->
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,727 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<meta name="viewport" content="width=device-width">
|
||||
|
||||
<title>How to Multi-Sign - Ripple Developer Portal</title>
|
||||
|
||||
<!-- favicon -->
|
||||
<link rel="icon" href="favicon.ico" type="image/x-icon">
|
||||
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon">
|
||||
|
||||
<!-- jQuery -->
|
||||
<script src="assets/vendor/jquery-1.11.1.min.js"></script>
|
||||
|
||||
<!-- Custom Stylesheets. ripple.css includes bootstrap, font stuff -->
|
||||
<link href="assets/css/ripple.css" rel="stylesheet" />
|
||||
<link href="assets/css/devportal.css" rel="stylesheet" />
|
||||
|
||||
<!-- Bootstrap JS -->
|
||||
<script src="assets/vendor/bootstrap.min.js"></script>
|
||||
|
||||
|
||||
<!-- syntax highlighting -->
|
||||
<link rel="stylesheet" href="assets/vendor/docco.min.css" />
|
||||
<script src="assets/vendor/highlight.min.js"></script>
|
||||
|
||||
<!-- syntax selection js -->
|
||||
<script src="assets/js/multicodetab.js"></script>
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
$(".multicode").minitabs();
|
||||
hljs.initHighlighting();
|
||||
make_code_expandable();
|
||||
});
|
||||
</script>
|
||||
|
||||
<script src="assets/js/expandcode.js"></script>
|
||||
<script src="assets/js/fixsidebarscroll.js"></script>
|
||||
|
||||
<!-- fontawesome icons -->
|
||||
<link rel="stylesheet" href="assets/vendor/fontawesome/css/font-awesome.min.css" />
|
||||
|
||||
</head>
|
||||
|
||||
<body class="page page-template page-template-template-dev-portal page-template-template-dev-portal-php sidebar-primary wpb-js-composer js-comp-ver-3.6.2 vc_responsive">
|
||||
<header role="banner" class="banner navbar navbar-default navbar-fixed-top initial_header">
|
||||
<div class="container">
|
||||
<div class="navbar-header">
|
||||
<a href="index.html" class="navbar-brand"><img src="assets/img/ripple-logo-color.png" class="logo"></a>
|
||||
</div><!-- /.navbar-header -->
|
||||
<div class="nav">
|
||||
<div class="draft-warning">DRAFT PAGE</div>
|
||||
</div><!-- /.nav -->
|
||||
|
||||
</div><!-- /.container -->
|
||||
|
||||
<div class="subnav dev_nav">
|
||||
<div class="container">
|
||||
<ul id="menu-dev-menu" class="menu">
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">References <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="reference-rippleapi.html">RippleAPI</a></li>
|
||||
<li><a href="reference-rippled.html">rippled</a></li>
|
||||
<li><a href="reference-transaction-format.html">Transaction Format</a></li>
|
||||
<li><a href="reference-ledger-format.html">Ledger Format</a></li>
|
||||
<li><a href="reference-data-api.html">Ripple Data API v2</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorials <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="tutorial-multisign.html">How to Multi-Sign</a></li>
|
||||
<li><a href="tutorial-paychan.html">Payment Channels Tutorial</a></li>
|
||||
<li><a href="concept-issuing-and-operational-addresses.html">Issuing and Operational Addresses</a></li>
|
||||
<li><a href="tutorial-reliable-transaction-submission.html">Reliable Transaction Submission</a></li>
|
||||
<li><a href="tutorial-rippleapi-beginners-guide.html">RippleAPI Beginners Guide</a></li>
|
||||
<li><a href="tutorial-rippled-setup.html">rippled Setup</a></li>
|
||||
<li><a href="tutorial-gateway-guide.html">Gateway Guide</a></li>
|
||||
<li><a href="tutorial-listing-xrp.html">Listing XRP as an Exchange</a></li>
|
||||
<li><a href="tutorial-escrow.html">Escrow Tutorials</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Features <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="concept-accounts.html">Accounts</a></li>
|
||||
<li><a href="concept-amendments.html">Amendments</a></li>
|
||||
<li><a href="concept-consensus.html">Consensus Process</a></li>
|
||||
<li><a href="concept-reaching-consensus.html">Reaching Consensus in the XRP Ledger</a></li>
|
||||
<li><a href="concept-fee-voting.html">Fee Voting</a></li>
|
||||
<li><a href="concept-fees.html">Fees (Disambiguation)</a></li>
|
||||
<li><a href="concept-freeze.html">Freeze</a></li>
|
||||
<li><a href="concept-partial-payments.html">Partial Payments</a></li>
|
||||
<li><a href="concept-paths.html">Paths</a></li>
|
||||
<li><a href="concept-reserves.html">Reserves</a></li>
|
||||
<li><a href="concept-stand-alone-mode.html">Stand-Alone Mode</a></li>
|
||||
<li><a href="concept-transaction-cost.html">Transaction Cost</a></li>
|
||||
<li><a href="concept-transfer-fees.html">Transfer Fees</a></li>
|
||||
<li><a href="concept-noripple.html">Understanding the NoRipple flag</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Gateway Bulletins <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="gb-2015-06.html">GB-2015-06: Corrections to Autobridging</a></li>
|
||||
<li><a href="gb-2015-05.html">GB-2015-05: Historical Ledger Query Migration</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">API Tools <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="ripple-api-tool.html">WebSocket API Tool</a></li>
|
||||
<li><a href="data-api-v2-tool.html">Data API v2 Tool</a></li>
|
||||
<li><a href="tool-jsonrpc.html">rippled JSON-RPC Tool</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li><a href="https://github.com/ripple/ripple-dev-portal" title="GitHub">Site Source</a></li>
|
||||
</ul><!-- /#dev-menu -->
|
||||
</div><!-- /.subnav .container -->
|
||||
</div><!-- /.subnav -->
|
||||
</header>
|
||||
|
||||
|
||||
<div class="wrap container" role="document">
|
||||
<aside class="sidebar" role="complementary">
|
||||
<div class="dev_nav_wrapper">
|
||||
<div id="cont">
|
||||
<h5>In this category:</h5>
|
||||
<ul class="dev_nav_sidebar">
|
||||
<li class="level-1"><a href="index.html">Category: Tutorials</a></li>
|
||||
<li class="level-2"><a href="tutorial-multisign.html">How to Multi-Sign</a></li>
|
||||
<li class="level-2"><a href="tutorial-paychan.html">Payment Channels Tutorial</a></li>
|
||||
<li class="level-2"><a href="concept-issuing-and-operational-addresses.html">Issuing and Operational Addresses</a></li>
|
||||
<li class="level-2"><a href="tutorial-reliable-transaction-submission.html">Reliable Transaction Submission</a></li>
|
||||
<li class="level-2"><a href="tutorial-rippleapi-beginners-guide.html">RippleAPI Beginners Guide</a></li>
|
||||
<li class="level-2"><a href="tutorial-rippled-setup.html">rippled Setup</a></li>
|
||||
<li class="level-2"><a href="tutorial-gateway-guide.html">Gateway Guide</a></li>
|
||||
<li class="level-2"><a href="tutorial-listing-xrp.html">Listing XRP as an Exchange</a></li>
|
||||
<li class="level-2"><a href="tutorial-escrow.html">Escrow Tutorials</a></li>
|
||||
</ul>
|
||||
<hr />
|
||||
<h5>In this page:</h5>
|
||||
<ul class="dev_nav_sidebar" id="dactyl_toc_sidebar">
|
||||
<li class="level-1"><a href="#how-to-multi-sign">How to Multi-Sign</a></li>
|
||||
<li class="level-2"><a href="#availability-of-multi-signing">Availability of Multi-Signing</a></li>
|
||||
<li class="level-2"><a href="#setting-up-multi-signing">Setting up Multi-Signing</a></li>
|
||||
<li class="level-3"><a href="#1-prepare-a-funded-address">1. Prepare a funded address</a></li>
|
||||
<li class="level-3"><a href="#2-prepare-member-keys">2. Prepare member keys</a></li>
|
||||
<li class="level-3"><a href="#3-send-signerlistset-transaction">3. Send SignerListSet transaction</a></li>
|
||||
<li class="level-3"><a href="#4-close-the-ledger">4. Close the ledger</a></li>
|
||||
<li class="level-3"><a href="#5-confirm-the-new-signer-list">5. Confirm the new signer list</a></li>
|
||||
<li class="level-3"><a href="#6-further-steps">6. Further steps</a></li>
|
||||
<li class="level-2"><a href="#sending-a-multi-signed-transaction">Sending a Multi-Signed Transaction</a></li>
|
||||
<li class="level-3"><a href="#1-create-the-transaction">1. Create the transaction</a></li>
|
||||
<li class="level-3"><a href="#2-get-one-signature">2. Get one signature</a></li>
|
||||
<li class="level-3"><a href="#3-get-additional-signatures">3. Get additional signatures</a></li>
|
||||
<li class="level-3"><a href="#4-combine-signatures-and-submit">4. Combine signatures and submit</a></li>
|
||||
<li class="level-3"><a href="#5-close-the-ledger">5. Close the ledger</a></li>
|
||||
<li class="level-3"><a href="#6-confirm-transaction-results">6. Confirm transaction results</a></li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
<main class="main" role="main">
|
||||
<div class='content'>
|
||||
<h1 id="how-to-multi-sign">How to Multi-Sign</h1>
|
||||
<p>Multi-signing is one of three ways to authorize transactions for the XRP Ledger, alongside signing with <a href="reference-transaction-format.html#setregularkey">regular keys</a> and master keys. You can configure your address to allow any combination of the three methods to authorize transactions.</p>
|
||||
<p>Benefits of multi-signing include:</p>
|
||||
<ul>
|
||||
<li>You can require keys from different devices, so that a malicious actor must compromise multiple machines to send transactions on your behalf.</li>
|
||||
<li>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.</li>
|
||||
<li>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.</li>
|
||||
<li>... and more.</li>
|
||||
</ul>
|
||||
<p>To use multi-signing:</p>
|
||||
<ol>
|
||||
<li><a href="#availability-of-multi-signing">The XRP Ledger peer-to-peer network must have multi-signing enabled.</a></li>
|
||||
<li><a href="#setting-up-multi-signing">Set up a list of signers on your account.</a></li>
|
||||
<li><a href="#sending-a-multi-signed-transaction">Send transactions using multiple signatures.</a></li>
|
||||
</ol>
|
||||
<h2 id="availability-of-multi-signing">Availability of Multi-Signing</h2>
|
||||
<p>Multi-signing has been enabled by an <a href="concept-amendments.html"><strong>Amendment</strong></a> to the XRP Ledger Consensus Protocol since 2016-06-27.</p>
|
||||
<p>If you want to use multi-signing with <code>rippled</code> with a fresh ledger in <a href="concept-stand-alone-mode.html">stand-alone mode</a>, you must force the MultiSign feature to be enabled. You can check the status of the MultiSign amendment using the <a href="reference-rippled.html#feature"><code>feature</code> command</a>.</p>
|
||||
<p>To force the multi-signing feature to be enabled, add the following stanza to your <code>rippled.cfg</code>: <!-- --></p>
|
||||
<pre><code>[features]
|
||||
MultiSign
|
||||
</code></pre>
|
||||
<h2 id="setting-up-multi-signing">Setting up Multi-Signing</h2>
|
||||
<p>To multi-sign transactions from a particular address, you must create a list of addresses that can contribute to a multi-signature for your address. This list is stored in the XRP Ledger as a <a href="reference-ledger-format.html#signerlist">SignerList node</a>. The following procedure demonstrates how to set up a SignerList for your address:</p>
|
||||
<h3 id="1-prepare-a-funded-address">1. Prepare a funded address</h3>
|
||||
<p>You need an XRP Ledger address that can send transactions, and has enough XRP available. Multi-signing requires more than the usual amount of XRP for the <a href="concept-reserves.html">account reserve</a> and <a href="concept-transaction-cost.html">transaction cost</a>, increasing with the number of signers and signatures you use.</p>
|
||||
<p>If you started <code>rippled</code> in <a href="concept-stand-alone-mode.html">stand-alone mode</a> with a new genesis ledger, you must:</p>
|
||||
<ol>
|
||||
<li>Generate keys for a new address, or reuse keys you already have.</li>
|
||||
<li>Submit a Payment transaction to fund the new address from the genesis account. (Send at least 100,000,000 <a href="reference-rippled.html#specifying-currency-amounts">drops of XRP</a>.)</li>
|
||||
<li>Manually close the ledger.</li>
|
||||
</ol>
|
||||
<h3 id="2-prepare-member-keys">2. Prepare member keys</h3>
|
||||
<p>You need several sets of XRP Ledger keys (address and secret) to include as members of your SignerList. These can be funded addresses that exist in the ledger, or you can generate new addresses using the <a href="reference-rippled.html#wallet-propose"><code>wallet_propose</code> command</a>. For example:</p>
|
||||
<pre><code>$ rippled wallet_propose
|
||||
Loading: "/home/mduo13/.config/ripple/rippled.cfg"
|
||||
Connecting to 127.0.0.1:5005
|
||||
{
|
||||
"result" : {
|
||||
"account_id" : "rnRJ4dpSBKDR2M1itf4Ah6tZZm5xuNZFPH",
|
||||
"key_type" : "secp256k1",
|
||||
"master_key" : "FLOG SEND GOES CUFF GAGE FAT ANTI DEL GUM TIRE ISLE BEAR",
|
||||
"master_seed" : "snheH5UUjU4CWqiNVLny2k21TyKPC",
|
||||
"master_seed_hex" : "A9F859765EB8614D26809836382AFB82",
|
||||
"public_key" : "aBR4hxFXcDNHnGYvTiqb2KU8TTTV1cYV9wXTAuz2DjBm7S8TYEBU",
|
||||
"public_key_hex" : "03C09A5D112B393D531E4F092E3A5769A5752129F0A9C55C61B3A226BB9B567B9B",
|
||||
"status" : "success"
|
||||
}
|
||||
}
|
||||
</code></pre>
|
||||
<p>Take note of the <code>account_id</code> (XRP Ledger Address) and <code>master_seed</code> (secret key) for each one you generate.</p>
|
||||
<h3 id="3-send-signerlistset-transaction">3. Send SignerListSet transaction</h3>
|
||||
<p><a href="reference-transaction-format.html#signing-and-submitting-transactions">Sign and submit</a> a <a href="reference-transaction-format.html#signerlistset">SignerListSet transaction</a> in the normal (single-signature) way. This associates a SignerList with your XRP Ledger address, so that a combination of signatures from the members of that SignerList can multi-sign later transactions on your behalf.</p>
|
||||
<p>In this example, the SignerList has 3 members, with the weights and quorum set up such that multi-signed transactions need a signature from rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW plus at least one signature from the other two members of the list.</p>
|
||||
<p class="devportal-callout caution"><strong>Caution:</strong> Never submit a secret key to a server you do not control. Do not send a secret key unencrypted over the network.</p>
|
||||
<pre><code>$ rippled submit shqZZy2Rzs9ZqWTCQAdqc3bKgxnYq '{
|
||||
> "Flags": 0,
|
||||
> "TransactionType": "SignerListSet",
|
||||
> "Account": "rnBFvgZphmN39GWzUJeUitaP22Fr9be75H",
|
||||
> "Fee": "10000",
|
||||
> "SignerQuorum": 3,
|
||||
> "SignerEntries": [
|
||||
> {
|
||||
> "SignerEntry": {
|
||||
> "Account": "rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW",
|
||||
> "SignerWeight": 2
|
||||
> }
|
||||
> },
|
||||
> {
|
||||
> "SignerEntry": {
|
||||
> "Account": "rUpy3eEg8rqjqfUoLeBnZkscbKbFsKXC3v",
|
||||
> "SignerWeight": 1
|
||||
> }
|
||||
> },
|
||||
> {
|
||||
> "SignerEntry": {
|
||||
> "Account": "raKEEVSGnKSD9Zyvxu4z6Pqpm4ABH8FS6n",
|
||||
> "SignerWeight": 1
|
||||
> }
|
||||
> }
|
||||
> ]
|
||||
> }'
|
||||
Loading: "/home/mduo13/.config/ripple/rippled.cfg"
|
||||
Connecting to 127.0.0.1:5005
|
||||
{
|
||||
"result" : {
|
||||
"engine_result" : "tesSUCCESS",
|
||||
"engine_result_code" : 0,
|
||||
"engine_result_message" : "The transaction was applied. Only final in a validated ledger.",
|
||||
"status" : "success",
|
||||
"tx_blob" : "12000C2200000000240000000120230000000368400000000000271073210303E20EC6B4A39A629815AE02C0A1393B9225E3B890CAE45B59F42FA29BE9668D74473045022100BEDFA12502C66DDCB64521972E5356F4DB965F553853D53D4C69B4897F11B4780220595202D1E080345B65BAF8EBD6CA161C227F1B62C7E72EA5CA282B9434A6F04281142DECAB42CA805119A9BA2FF305C9AFA12F0B86A1F4EB1300028114204288D2E47F8EF6C99BCC457966320D12409711E1EB13000181147908A7F0EDD48EA896C3580A399F0EE78611C8E3E1EB13000181143A4C02EA95AD6AC3BED92FA036E0BBFB712C030CE1F1",
|
||||
"tx_json" : {
|
||||
"Account" : "rnBFvgZphmN39GWzUJeUitaP22Fr9be75H",
|
||||
"Fee" : "10000",
|
||||
"Flags" : 0,
|
||||
"Sequence" : 1,
|
||||
"SignerEntries" : [
|
||||
{
|
||||
"SignerEntry" : {
|
||||
"Account" : "rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW",
|
||||
"SignerWeight" : 2
|
||||
}
|
||||
},
|
||||
{
|
||||
"SignerEntry" : {
|
||||
"Account" : "rUpy3eEg8rqjqfUoLeBnZkscbKbFsKXC3v",
|
||||
"SignerWeight" : 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"SignerEntry" : {
|
||||
"Account" : "raKEEVSGnKSD9Zyvxu4z6Pqpm4ABH8FS6n",
|
||||
"SignerWeight" : 1
|
||||
}
|
||||
}
|
||||
],
|
||||
"SignerQuorum" : 3,
|
||||
"SigningPubKey" : "0303E20EC6B4A39A629815AE02C0A1393B9225E3B890CAE45B59F42FA29BE9668D",
|
||||
"TransactionType" : "SignerListSet",
|
||||
"TxnSignature" : "3045022100BEDFA12502C66DDCB64521972E5356F4DB965F553853D53D4C69B4897F11B4780220595202D1E080345B65BAF8EBD6CA161C227F1B62C7E72EA5CA282B9434A6F042",
|
||||
"hash" : "3950D98AD20DA52EBB1F3937EF32F382D74092A4C8DF9A0B1A06ED25200B5756"
|
||||
}
|
||||
}
|
||||
}
|
||||
</code></pre>
|
||||
<p>Make sure that the <a href="reference-transaction-format.html#transaction-results">Transaction Result</a> is <a href="reference-transaction-format.html#tes-success"><strong>tesSUCCESS</strong></a>. Otherwise, the transaction failed. If you encounter a problem in stand-alone mode or a non-production network, check that <a href="#availability-of-multi-signing">multi-sign is enabled</a>.</p>
|
||||
<p class="devportal-callout note"><strong>Note:</strong> The more members in the SignerList, the more XRP your address must have for purposes of the <a href="concept-reserves.html#owner-reserves">owner reserve</a>. If your address does not have enough XRP, the transaction fails with <a href="reference-transaction-format.html#tec-codes">tecINSUFFICIENT_RESERVE</a>. See also: <a href="reference-ledger-format.html#signerlists-and-reserves">SignerLists and Reserves</a>.</p>
|
||||
<h3 id="4-close-the-ledger">4. Close the ledger</h3>
|
||||
<p>On the live network, you can wait 4-7 seconds for the ledger to close automatically.</p>
|
||||
<p>If you're running <code>rippled</code> in stand-alone mode, use the <a href="reference-rippled.html#ledger-accept"><code>ledger_accept</code> command</a> to manually close the ledger:</p>
|
||||
<pre><code>$ rippled ledger_accept
|
||||
Loading: "/home/mduo13/.config/ripple/rippled.cfg"
|
||||
Connecting to 127.0.0.1:5005
|
||||
{
|
||||
"result" : {
|
||||
"ledger_current_index" : 6,
|
||||
"status" : "success"
|
||||
}
|
||||
}
|
||||
</code></pre>
|
||||
<h3 id="5-confirm-the-new-signer-list">5. Confirm the new signer list</h3>
|
||||
<p>Use the <a href="reference-rippled.html#account-objects"><code>account_objects</code> command</a> to confirm that the SignerList is associated with the address in the latest validated ledger.</p>
|
||||
<p>Normally, an account can own many objects of different types (such as trust lines and offers). If you funded a new address for this tutorial, the SignerList is the only object in the response.</p>
|
||||
<pre><code>$ rippled account_objects rEuLyBCvcw4CFmzv8RepSiAoNgF8tTGJQC validated
|
||||
Loading: "/home/mduo13/.config/ripple/rippled.cfg"
|
||||
Connecting to 127.0.0.1:5005
|
||||
{
|
||||
"result" : {
|
||||
"account" : "rEuLyBCvcw4CFmzv8RepSiAoNgF8tTGJQC",
|
||||
"account_objects" : [
|
||||
{
|
||||
"Flags" : 0,
|
||||
"LedgerEntryType" : "SignerList",
|
||||
"OwnerNode" : "0000000000000000",
|
||||
"PreviousTxnID" : "8FDC18960455C196A8C4DE0D24799209A21F4A17E32102B5162BD79466B90222",
|
||||
"PreviousTxnLgrSeq" : 5,
|
||||
"SignerEntries" : [
|
||||
{
|
||||
"SignerEntry" : {
|
||||
"Account" : "rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW",
|
||||
"SignerWeight" : 2
|
||||
}
|
||||
},
|
||||
{
|
||||
"SignerEntry" : {
|
||||
"Account" : "raKEEVSGnKSD9Zyvxu4z6Pqpm4ABH8FS6n",
|
||||
"SignerWeight" : 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"SignerEntry" : {
|
||||
"Account" : "rUpy3eEg8rqjqfUoLeBnZkscbKbFsKXC3v",
|
||||
"SignerWeight" : 1
|
||||
}
|
||||
}
|
||||
],
|
||||
"SignerListID" : 0,
|
||||
"SignerQuorum" : 3,
|
||||
"index" : "79FD203E4DDDF2EA78B798C963487120C048C78652A28682425E47C96D016F92"
|
||||
}
|
||||
],
|
||||
"ledger_hash" : "56E81069F06492FB410A70218C08169BE3AB3CFD5AEA20E999662D81DC361D9F",
|
||||
"ledger_index" : 5,
|
||||
"status" : "success",
|
||||
"validated" : true
|
||||
}
|
||||
}
|
||||
</code></pre>
|
||||
<p>If the SignerList is present with the expected contents, then your address is ready to multi-sign.</p>
|
||||
<h3 id="6-further-steps">6. Further steps</h3>
|
||||
<p>At this point, your address is ready to <a href="#sending-a-multi-signed-transaction">send a multi-signed transaction</a>. You may also want to:</p>
|
||||
<ul>
|
||||
<li>Disable the address's master key pair by sending an <a href="reference-transaction-format.html#accountset">AccountSet transaction</a> using the <code>asfDisableMaster</code> flag.</li>
|
||||
<li>Remove the address's regular key pair (if you previously set one) by sending a <a href="reference-transaction-format.html#setregularkey">SetRegularKey transaction</a>.</li>
|
||||
</ul>
|
||||
<h2 id="sending-a-multi-signed-transaction">Sending a Multi-Signed Transaction</h2>
|
||||
<p>Before you can multi-sign a transaction, first <a href="#setting-up-multi-signing">set up multi-signing</a> for your address. The following procedure demonstrates how to create, sign, and submit a multi-signed transaction.</p>
|
||||
<h3 id="1-create-the-transaction">1. Create the transaction</h3>
|
||||
<p>Create a JSON object that represents the transaction you want to submit. You have to specify <em>everything</em> about this transaction, including <code>Fee</code> and <code>Sequence</code>. Also include the field <code>SigningPubKey</code> as an empty string, to indicate that the transaction is multi-signed.</p>
|
||||
<p>Keep in mind that the <code>Fee</code> for multi-signed transactions is significantly higher than for regularly-signed transactions. It should be at least (N+1) times the normal <a href="concept-transaction-cost.html">transaction cost</a>, where N is the number of signatures you plan to provide. Since it sometimes takes a while to collect signatures from multiple sources, you may want to specify more than the current minimum, in case the <a href="concept-transaction-cost.html">transaction cost</a> increases in that time.</p>
|
||||
<p>Here's an example transaction ready to be multi-signed:</p>
|
||||
<pre><code>{
|
||||
"TransactionType": "TrustSet",
|
||||
"Account": "rEuLyBCvcw4CFmzv8RepSiAoNgF8tTGJQC",
|
||||
"Flags": 262144,
|
||||
"LimitAmount": {
|
||||
"currency": "USD",
|
||||
"issuer": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
|
||||
"value": "100"
|
||||
},
|
||||
"Sequence": 2,
|
||||
"SigningPubKey": "",
|
||||
"Fee": "30000"
|
||||
}
|
||||
</code></pre>
|
||||
<p>(This transaction creates an accounting relationship from rEuLyBCvcw4CFmzv8RepSiAoNgF8tTGJQC to rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh with a maximum balance of 100 USD.)</p>
|
||||
<h3 id="2-get-one-signature">2. Get one signature</h3>
|
||||
<p>Use the <a href="reference-rippled.html#sign-for"><code>sign_for</code> command</a> with the secret key and address of one of the members of your SignerList to get a signature for that member.</p>
|
||||
<p class="devportal-callout caution"><strong>Caution:</strong> Never submit a secret key to a server you do not control. Do not send a secret key unencrypted over the network.</p>
|
||||
<pre><code>$ rippled sign_for rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW <rsA2L..'s secret> '{
|
||||
> "TransactionType": "TrustSet",
|
||||
> "Account": "rEuLyBCvcw4CFmzv8RepSiAoNgF8tTGJQC",
|
||||
> "Flags": 262144,
|
||||
> "LimitAmount": {
|
||||
> "currency": "USD",
|
||||
> "issuer": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
|
||||
> "value": "100"
|
||||
> },
|
||||
> "Sequence": 2,
|
||||
> "SigningPubKey": "",
|
||||
> "Fee": "30000"
|
||||
> }'
|
||||
Loading: "/home/mduo13/.config/ripple/rippled.cfg"
|
||||
Connecting to 127.0.0.1:5005
|
||||
{
|
||||
"result" : {
|
||||
"status" : "success",
|
||||
"tx_blob" : "1200142200040000240000000263D5038D7EA4C680000000000000000000000000005553440000000000B5F762798A53D543A014CAF8B297CFF8F2F937E868400000000000753073008114A3780F5CB5A44D366520FC44055E8ED44D9A2270F3E010732102B3EC4E5DD96029A647CFA20DA07FE1F85296505552CCAC114087E66B46BD77DF744730450221009C195DBBF7967E223D8626CA19CF02073667F2B22E206727BFE848FF42BEAC8A022048C323B0BED19A988BDBEFA974B6DE8AA9DCAE250AA82BBD1221787032A864E58114204288D2E47F8EF6C99BCC457966320D12409711E1F1",
|
||||
"tx_json" : {
|
||||
"Account" : "rEuLyBCvcw4CFmzv8RepSiAoNgF8tTGJQC",
|
||||
"Fee" : "30000",
|
||||
"Flags" : 262144,
|
||||
"LimitAmount" : {
|
||||
"currency" : "USD",
|
||||
"issuer" : "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
|
||||
"value" : "100"
|
||||
},
|
||||
"Sequence" : 2,
|
||||
"Signers" : [
|
||||
{
|
||||
"Signer" : {
|
||||
"Account" : "rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW",
|
||||
"SigningPubKey" : "02B3EC4E5DD96029A647CFA20DA07FE1F85296505552CCAC114087E66B46BD77DF",
|
||||
"TxnSignature" : "30450221009C195DBBF7967E223D8626CA19CF02073667F2B22E206727BFE848FF42BEAC8A022048C323B0BED19A988BDBEFA974B6DE8AA9DCAE250AA82BBD1221787032A864E5"
|
||||
}
|
||||
}
|
||||
],
|
||||
"SigningPubKey" : "",
|
||||
"TransactionType" : "TrustSet",
|
||||
"hash" : "A94A6417D1A7AAB059822B894E13D322ED3712F7212CE9257801F96DE6C3F6AE"
|
||||
}
|
||||
}
|
||||
}
|
||||
</code></pre>
|
||||
<p>Save the <code>tx_json</code> field of the response: it has the new signature in the <code>Signers</code> field. You can discard the value of the <code>tx_blob</code> field.</p>
|
||||
<p>If you encounter a problem in stand-alone mode or a non-production network, check that <a href="#availability-of-multi-signing">multi-sign is enabled</a>.</p>
|
||||
<h3 id="3-get-additional-signatures">3. Get additional signatures</h3>
|
||||
<p>You can collect additional signatures in parallel or in serial:</p>
|
||||
<ul>
|
||||
<li>In parallel: Use the <code>sign_for</code> command with the original JSON for the transaction. Each response has a single signature in the <code>Signers</code> array.</li>
|
||||
<li>In serial: Use the <code>sign_for</code> command with the <code>tx_json</code> value from the previous <code>sign_for</code> response. Each response adds a new signature to the existing <code>Signers</code> array.</li>
|
||||
</ul>
|
||||
<p class="devportal-callout caution"><strong>Caution:</strong> Never submit a secret key to a server you do not control. Do not send a secret key unencrypted over the network.</p>
|
||||
<pre><code>$ rippled sign_for rUpy3eEg8rqjqfUoLeBnZkscbKbFsKXC3v <rUpy..'s secret> '{
|
||||
> "Account" : "rEuLyBCvcw4CFmzv8RepSiAoNgF8tTGJQC",
|
||||
> "Fee" : "30000",
|
||||
> "Flags" : 262144,
|
||||
> "LimitAmount" : {
|
||||
> "currency" : "USD",
|
||||
> "issuer" : "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
|
||||
> "value" : "100"
|
||||
> },
|
||||
> "Sequence" : 2,
|
||||
> "Signers" : [
|
||||
> {
|
||||
> "Signer" : {
|
||||
> "Account" : "rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW",
|
||||
> "SigningPubKey" : "02B3EC4E5DD96029A647CFA20DA07FE1F85296505552CCAC114087E66B46BD77DF",
|
||||
> "TxnSignature" : "30450221009C195DBBF7967E223D8626CA19CF02073667F2B22E206727BFE848FF42BEAC8A022048C323B0BED19A988BDBEFA974B6DE8AA9DCAE250AA82BBD1221787032A864E5"
|
||||
> }
|
||||
> }
|
||||
> ],
|
||||
> "SigningPubKey" : "",
|
||||
> "TransactionType" : "TrustSet",
|
||||
> "hash" : "A94A6417D1A7AAB059822B894E13D322ED3712F7212CE9257801F96DE6C3F6AE"
|
||||
> }'
|
||||
Loading: "/home/mduo13/.config/ripple/rippled.cfg"
|
||||
Connecting to 127.0.0.1:5005
|
||||
{
|
||||
"result" : {
|
||||
"status" : "success",
|
||||
"tx_blob" : "1200142200040000240000000263D5038D7EA4C680000000000000000000000000005553440000000000B5F762798A53D543A014CAF8B297CFF8F2F937E868400000000000753073008114A3780F5CB5A44D366520FC44055E8ED44D9A2270F3E010732102B3EC4E5DD96029A647CFA20DA07FE1F85296505552CCAC114087E66B46BD77DF744730450221009C195DBBF7967E223D8626CA19CF02073667F2B22E206727BFE848FF42BEAC8A022048C323B0BED19A988BDBEFA974B6DE8AA9DCAE250AA82BBD1221787032A864E58114204288D2E47F8EF6C99BCC457966320D12409711E1E0107321028FFB276505F9AC3F57E8D5242B386A597EF6C40A7999F37F1948636FD484E25B744630440220680BBD745004E9CFB6B13A137F505FB92298AD309071D16C7B982825188FD1AE022004200B1F7E4A6A84BB0E4FC09E1E3BA2B66EBD32F0E6D121A34BA3B04AD99BC181147908A7F0EDD48EA896C3580A399F0EE78611C8E3E1F1",
|
||||
"tx_json" : {
|
||||
"Account" : "rEuLyBCvcw4CFmzv8RepSiAoNgF8tTGJQC",
|
||||
"Fee" : "30000",
|
||||
"Flags" : 262144,
|
||||
"LimitAmount" : {
|
||||
"currency" : "USD",
|
||||
"issuer" : "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
|
||||
"value" : "100"
|
||||
},
|
||||
"Sequence" : 2,
|
||||
"Signers" : [
|
||||
{
|
||||
"Signer" : {
|
||||
"Account" : "rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW",
|
||||
"SigningPubKey" : "02B3EC4E5DD96029A647CFA20DA07FE1F85296505552CCAC114087E66B46BD77DF",
|
||||
"TxnSignature" : "30450221009C195DBBF7967E223D8626CA19CF02073667F2B22E206727BFE848FF42BEAC8A022048C323B0BED19A988BDBEFA974B6DE8AA9DCAE250AA82BBD1221787032A864E5"
|
||||
}
|
||||
},
|
||||
{
|
||||
"Signer" : {
|
||||
"Account" : "rUpy3eEg8rqjqfUoLeBnZkscbKbFsKXC3v",
|
||||
"SigningPubKey" : "028FFB276505F9AC3F57E8D5242B386A597EF6C40A7999F37F1948636FD484E25B",
|
||||
"TxnSignature" : "30440220680BBD745004E9CFB6B13A137F505FB92298AD309071D16C7B982825188FD1AE022004200B1F7E4A6A84BB0E4FC09E1E3BA2B66EBD32F0E6D121A34BA3B04AD99BC1"
|
||||
}
|
||||
}
|
||||
],
|
||||
"SigningPubKey" : "",
|
||||
"TransactionType" : "TrustSet",
|
||||
"hash" : "BD636194C48FD7A100DE4C972336534C8E710FD008C0F3CF7BC5BF34DAF3C3E6"
|
||||
}
|
||||
}
|
||||
}
|
||||
</code></pre>
|
||||
<p>Depending on the SignerList you configured, you may need to repeat this step several times to get signatures from all the necessary parties.</p>
|
||||
<h3 id="4-combine-signatures-and-submit">4. Combine signatures and submit</h3>
|
||||
<p>If you collected the signatures in serial, the <code>tx_json</code> from the last <code>sign_for</code> response has all the signatures assembled, so you can use that as the argument to the <a href="reference-rippled.html#submit-multisigned"><code>submit_multisigned</code> command</a>.</p>
|
||||
<p>If you collected the signatures in parallel, you must manually construct a <code>tx_json</code> object with all the signatures included. Take the <code>Signers</code> arrays from all the <code>sign_for</code> responses, and combine their contents into a single <code>Signers</code> array that has each signature. Add the combined <code>Signers</code> array to the original transaction JSON value, and use that as the argument to the <a href="reference-rippled.html#submit-multisigned"><code>submit_multisigned</code> command</a>.</p>
|
||||
<pre><code>$ rippled submit_multisigned '{
|
||||
> "Account" : "rEuLyBCvcw4CFmzv8RepSiAoNgF8tTGJQC",
|
||||
> "Fee" : "30000",
|
||||
> "Flags" : 262144,
|
||||
> "LimitAmount" : {
|
||||
> "currency" : "USD",
|
||||
> "issuer" : "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
|
||||
> "value" : "100"
|
||||
> },
|
||||
> "Sequence" : 2,
|
||||
> "Signers" : [
|
||||
> {
|
||||
> "Signer" : {
|
||||
> "Account" : "rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW",
|
||||
> "SigningPubKey" : "02B3EC4E5DD96029A647CFA20DA07FE1F85296505552CCAC114087E66B46BD77DF",
|
||||
> "TxnSignature" : "30450221009C195DBBF7967E223D8626CA19CF02073667F2B22E206727BFE848FF42BEAC8A022048C323B0BED19A988BDBEFA974B6DE8AA9DCAE250AA82BBD1221787032A864E5"
|
||||
> }
|
||||
> },
|
||||
> {
|
||||
> "Signer" : {
|
||||
> "Account" : "rUpy3eEg8rqjqfUoLeBnZkscbKbFsKXC3v",
|
||||
> "SigningPubKey" : "028FFB276505F9AC3F57E8D5242B386A597EF6C40A7999F37F1948636FD484E25B",
|
||||
> "TxnSignature" : "30440220680BBD745004E9CFB6B13A137F505FB92298AD309071D16C7B982825188FD1AE022004200B1F7E4A6A84BB0E4FC09E1E3BA2B66EBD32F0E6D121A34BA3B04AD99BC1"
|
||||
> }
|
||||
> }
|
||||
> ],
|
||||
> "SigningPubKey" : "",
|
||||
> "TransactionType" : "TrustSet",
|
||||
> "hash" : "BD636194C48FD7A100DE4C972336534C8E710FD008C0F3CF7BC5BF34DAF3C3E6"
|
||||
> }'
|
||||
Loading: "/home/mduo13/.config/ripple/rippled.cfg"
|
||||
Connecting to 127.0.0.1:5005
|
||||
{
|
||||
"result": {
|
||||
"engine_result": "tesSUCCESS",
|
||||
"engine_result_code": 0,
|
||||
"engine_result_message": "The transaction was applied. Only final in a validated ledger.",
|
||||
"status": "success",
|
||||
"tx_blob": "1200142200040000240000000263D5038D7EA4C680000000000000000000000000005553440000000000B5F762798A53D543A014CAF8B297CFF8F2F937E868400000000000753073008114A3780F5CB5A44D366520FC44055E8ED44D9A2270F3E010732102B3EC4E5DD96029A647CFA20DA07FE1F85296505552CCAC114087E66B46BD77DF744730450221009C195DBBF7967E223D8626CA19CF02073667F2B22E206727BFE848FF42BEAC8A022048C323B0BED19A988BDBEFA974B6DE8AA9DCAE250AA82BBD1221787032A864E58114204288D2E47F8EF6C99BCC457966320D12409711E1E0107321028FFB276505F9AC3F57E8D5242B386A597EF6C40A7999F37F1948636FD484E25B744630440220680BBD745004E9CFB6B13A137F505FB92298AD309071D16C7B982825188FD1AE022004200B1F7E4A6A84BB0E4FC09E1E3BA2B66EBD32F0E6D121A34BA3B04AD99BC181147908A7F0EDD48EA896C3580A399F0EE78611C8E3E1F1",
|
||||
"tx_json": {
|
||||
"Account": "rEuLyBCvcw4CFmzv8RepSiAoNgF8tTGJQC",
|
||||
"Fee": "30000",
|
||||
"Flags": 262144,
|
||||
"LimitAmount": {
|
||||
"currency": "USD",
|
||||
"issuer": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
|
||||
"value": "100"
|
||||
},
|
||||
"Sequence": 2,
|
||||
"Signers": [{
|
||||
"Signer": {
|
||||
"Account": "rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW",
|
||||
"SigningPubKey": "02B3EC4E5DD96029A647CFA20DA07FE1F85296505552CCAC114087E66B46BD77DF",
|
||||
"TxnSignature": "30450221009C195DBBF7967E223D8626CA19CF02073667F2B22E206727BFE848FF42BEAC8A022048C323B0BED19A988BDBEFA974B6DE8AA9DCAE250AA82BBD1221787032A864E5"
|
||||
}
|
||||
}, {
|
||||
"Signer": {
|
||||
"Account": "rUpy3eEg8rqjqfUoLeBnZkscbKbFsKXC3v",
|
||||
"SigningPubKey": "028FFB276505F9AC3F57E8D5242B386A597EF6C40A7999F37F1948636FD484E25B",
|
||||
"TxnSignature": "30440220680BBD745004E9CFB6B13A137F505FB92298AD309071D16C7B982825188FD1AE022004200B1F7E4A6A84BB0E4FC09E1E3BA2B66EBD32F0E6D121A34BA3B04AD99BC1"
|
||||
}
|
||||
}],
|
||||
"SigningPubKey": "",
|
||||
"TransactionType": "TrustSet",
|
||||
"hash": "BD636194C48FD7A100DE4C972336534C8E710FD008C0F3CF7BC5BF34DAF3C3E6"
|
||||
}
|
||||
}
|
||||
}
|
||||
</code></pre>
|
||||
<p>Take note of the <code>hash</code> value from the response so you can check the results of the transaction later. (In this case, the hash is <code>BD636194C48FD7A100DE4C972336534C8E710FD008C0F3CF7BC5BF34DAF3C3E6</code>.)</p>
|
||||
<h3 id="5-close-the-ledger">5. Close the ledger</h3>
|
||||
<p>If you are using the live network, you can wait 4-7 seconds for the ledger to close automatically.</p>
|
||||
<p>If you're running <code>rippled</code> in stand-alone mode, use the <a href="reference-rippled.html#ledger-accept"><code>ledger_accept</code> command</a> to manually close the ledger:</p>
|
||||
<pre><code>$ rippled ledger_accept
|
||||
Loading: "/home/mduo13/.config/ripple/rippled.cfg"
|
||||
Connecting to 127.0.0.1:5005
|
||||
{
|
||||
"result" : {
|
||||
"ledger_current_index" : 7,
|
||||
"status" : "success"
|
||||
}
|
||||
}
|
||||
</code></pre>
|
||||
<h3 id="6-confirm-transaction-results">6. Confirm transaction results</h3>
|
||||
<p>Use the hash value from the response to the <code>submit_multisigned</code> command to look up the transaction using the <a href="reference-rippled.html#tx"><code>tx</code> command</a>. In particular, check that the <code>TransactionResult</code> is the string <code>tesSUCCESS</code>.</p>
|
||||
<p>On the live network, you must also confirm that the <code>validated</code> field is set to the boolean <code>true</code>. If the field is not <code>true</code>, you might need to wait longer for the consensus process to finish; or your transaction may be unable to be included in a ledger for some reason.</p>
|
||||
<p>In stand-alone mode, the server automatically considers a ledger to be <code>validated</code> if it has been manually closed.</p>
|
||||
<pre><code>$ rippled tx BD636194C48FD7A100DE4C972336534C8E710FD008C0F3CF7BC5BF34DAF3C3E6
|
||||
Loading: "/home/mduo13/.config/ripple/rippled.cfg"
|
||||
Connecting to 127.0.0.1:5005
|
||||
{
|
||||
"result": {
|
||||
"Account": "rEuLyBCvcw4CFmzv8RepSiAoNgF8tTGJQC",
|
||||
"Fee": "30000",
|
||||
"Flags": 262144,
|
||||
"LimitAmount": {
|
||||
"currency": "USD",
|
||||
"issuer": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
|
||||
"value": "100"
|
||||
},
|
||||
"Sequence": 2,
|
||||
"Signers": [{
|
||||
"Signer": {
|
||||
"Account": "rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW",
|
||||
"SigningPubKey": "02B3EC4E5DD96029A647CFA20DA07FE1F85296505552CCAC114087E66B46BD77DF",
|
||||
"TxnSignature": "30450221009C195DBBF7967E223D8626CA19CF02073667F2B22E206727BFE848FF42BEAC8A022048C323B0BED19A988BDBEFA974B6DE8AA9DCAE250AA82BBD1221787032A864E5"
|
||||
}
|
||||
}, {
|
||||
"Signer": {
|
||||
"Account": "rUpy3eEg8rqjqfUoLeBnZkscbKbFsKXC3v",
|
||||
"SigningPubKey": "028FFB276505F9AC3F57E8D5242B386A597EF6C40A7999F37F1948636FD484E25B",
|
||||
"TxnSignature": "30440220680BBD745004E9CFB6B13A137F505FB92298AD309071D16C7B982825188FD1AE022004200B1F7E4A6A84BB0E4FC09E1E3BA2B66EBD32F0E6D121A34BA3B04AD99BC1"
|
||||
}
|
||||
}],
|
||||
"SigningPubKey": "",
|
||||
"TransactionType": "TrustSet",
|
||||
"date": 512172510,
|
||||
"hash": "BD636194C48FD7A100DE4C972336534C8E710FD008C0F3CF7BC5BF34DAF3C3E6",
|
||||
"inLedger": 6,
|
||||
"ledger_index": 6,
|
||||
"meta": {
|
||||
"AffectedNodes": [{
|
||||
"ModifiedNode": {
|
||||
"LedgerEntryType": "AccountRoot",
|
||||
"LedgerIndex": "2B6AC232AA4C4BE41BF49D2459FA4A0347E1B543A4C92FCEE0821C0201E2E9A8",
|
||||
"PreviousTxnID": "B7E1D33DB7DEA3BB65BFAB2C80E02125F47FCCF6C957A7FDECD915B3EBE0C1DD",
|
||||
"PreviousTxnLgrSeq": 4
|
||||
}
|
||||
}, {
|
||||
"CreatedNode": {
|
||||
"LedgerEntryType": "RippleState",
|
||||
"LedgerIndex": "93E317B32022977C77810A2C558FBB28E30E744C68E73720622B797F957EC5FA",
|
||||
"NewFields": {
|
||||
"Balance": {
|
||||
"currency": "USD",
|
||||
"issuer": "rrrrrrrrrrrrrrrrrrrrBZbvji",
|
||||
"value": "0"
|
||||
},
|
||||
"Flags": 2162688,
|
||||
"HighLimit": {
|
||||
"currency": "USD",
|
||||
"issuer": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
|
||||
"value": "0"
|
||||
},
|
||||
"LowLimit": {
|
||||
"currency": "USD",
|
||||
"issuer": "rEuLyBCvcw4CFmzv8RepSiAoNgF8tTGJQC",
|
||||
"value": "100"
|
||||
}
|
||||
}
|
||||
}
|
||||
}, {
|
||||
"ModifiedNode": {
|
||||
"FinalFields": {
|
||||
"Account": "rEuLyBCvcw4CFmzv8RepSiAoNgF8tTGJQC",
|
||||
"Balance": "999960000",
|
||||
"Flags": 0,
|
||||
"OwnerCount": 6,
|
||||
"Sequence": 3
|
||||
},
|
||||
"LedgerEntryType": "AccountRoot",
|
||||
"LedgerIndex": "A6B1BA6F2D70813100908EA84ABB7783695050312735E2C3665259F388804EA0",
|
||||
"PreviousFields": {
|
||||
"Balance": "999990000",
|
||||
"OwnerCount": 5,
|
||||
"Sequence": 2
|
||||
},
|
||||
"PreviousTxnID": "8FDC18960455C196A8C4DE0D24799209A21F4A17E32102B5162BD79466B90222",
|
||||
"PreviousTxnLgrSeq": 5
|
||||
}
|
||||
}, {
|
||||
"ModifiedNode": {
|
||||
"FinalFields": {
|
||||
"Flags": 0,
|
||||
"Owner": "rEuLyBCvcw4CFmzv8RepSiAoNgF8tTGJQC",
|
||||
"RootIndex": "C2728175908D82FB1DE6676F203D8D3C056995A9FA9B369EF326523F1C65A1DE"
|
||||
},
|
||||
"LedgerEntryType": "DirectoryNode",
|
||||
"LedgerIndex": "C2728175908D82FB1DE6676F203D8D3C056995A9FA9B369EF326523F1C65A1DE"
|
||||
}
|
||||
}, {
|
||||
"CreatedNode": {
|
||||
"LedgerEntryType": "DirectoryNode",
|
||||
"LedgerIndex": "D8120FC732737A2CF2E9968FDF3797A43B457F2A81AA06D2653171A1EA635204",
|
||||
"NewFields": {
|
||||
"Owner": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
|
||||
"RootIndex": "D8120FC732737A2CF2E9968FDF3797A43B457F2A81AA06D2653171A1EA635204"
|
||||
}
|
||||
}
|
||||
}],
|
||||
"TransactionIndex": 0,
|
||||
"TransactionResult": "tesSUCCESS"
|
||||
},
|
||||
"status": "success",
|
||||
"validated": true
|
||||
}
|
||||
}
|
||||
</code></pre>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<footer class="content-info" role="contentinfo">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-sm-12 absolute_bottom_footer">
|
||||
<div class="col-sm-8">
|
||||
<span>© 2013 - 2017 Ripple Labs, Inc. All Rights Reserved.</span>
|
||||
<span><a href="/terms-of-use/">Terms</a></span>
|
||||
<span><a href="/privacy-policy/">Privacy</a></span>
|
||||
</div>
|
||||
</div><!-- /.absolute_bottom_footer -->
|
||||
|
||||
</div><!-- /.row -->
|
||||
</div><!-- /.container -->
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,750 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<meta name="viewport" content="width=device-width">
|
||||
|
||||
<title>Payment Channels Tutorial - Ripple Developer Portal</title>
|
||||
|
||||
<!-- favicon -->
|
||||
<link rel="icon" href="favicon.ico" type="image/x-icon">
|
||||
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon">
|
||||
|
||||
<!-- jQuery -->
|
||||
<script src="assets/vendor/jquery-1.11.1.min.js"></script>
|
||||
|
||||
<!-- Custom Stylesheets. ripple.css includes bootstrap, font stuff -->
|
||||
<link href="assets/css/ripple.css" rel="stylesheet" />
|
||||
<link href="assets/css/devportal.css" rel="stylesheet" />
|
||||
|
||||
<!-- Bootstrap JS -->
|
||||
<script src="assets/vendor/bootstrap.min.js"></script>
|
||||
|
||||
|
||||
<!-- syntax highlighting -->
|
||||
<link rel="stylesheet" href="assets/vendor/docco.min.css" />
|
||||
<script src="assets/vendor/highlight.min.js"></script>
|
||||
|
||||
<!-- syntax selection js -->
|
||||
<script src="assets/js/multicodetab.js"></script>
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
$(".multicode").minitabs();
|
||||
hljs.initHighlighting();
|
||||
make_code_expandable();
|
||||
});
|
||||
</script>
|
||||
|
||||
<script src="assets/js/expandcode.js"></script>
|
||||
<script src="assets/js/fixsidebarscroll.js"></script>
|
||||
|
||||
<!-- fontawesome icons -->
|
||||
<link rel="stylesheet" href="assets/vendor/fontawesome/css/font-awesome.min.css" />
|
||||
|
||||
</head>
|
||||
|
||||
<body class="page page-template page-template-template-dev-portal page-template-template-dev-portal-php sidebar-primary wpb-js-composer js-comp-ver-3.6.2 vc_responsive">
|
||||
<header role="banner" class="banner navbar navbar-default navbar-fixed-top initial_header">
|
||||
<div class="container">
|
||||
<div class="navbar-header">
|
||||
<a href="index.html" class="navbar-brand"><img src="assets/img/ripple-logo-color.png" class="logo"></a>
|
||||
</div><!-- /.navbar-header -->
|
||||
<div class="nav">
|
||||
<div class="draft-warning">DRAFT PAGE</div>
|
||||
</div><!-- /.nav -->
|
||||
|
||||
</div><!-- /.container -->
|
||||
|
||||
<div class="subnav dev_nav">
|
||||
<div class="container">
|
||||
<ul id="menu-dev-menu" class="menu">
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">References <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="reference-rippleapi.html">RippleAPI</a></li>
|
||||
<li><a href="reference-rippled.html">rippled</a></li>
|
||||
<li><a href="reference-transaction-format.html">Transaction Format</a></li>
|
||||
<li><a href="reference-ledger-format.html">Ledger Format</a></li>
|
||||
<li><a href="reference-data-api.html">Ripple Data API v2</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorials <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="tutorial-multisign.html">How to Multi-Sign</a></li>
|
||||
<li><a href="tutorial-paychan.html">Payment Channels Tutorial</a></li>
|
||||
<li><a href="concept-issuing-and-operational-addresses.html">Issuing and Operational Addresses</a></li>
|
||||
<li><a href="tutorial-reliable-transaction-submission.html">Reliable Transaction Submission</a></li>
|
||||
<li><a href="tutorial-rippleapi-beginners-guide.html">RippleAPI Beginners Guide</a></li>
|
||||
<li><a href="tutorial-rippled-setup.html">rippled Setup</a></li>
|
||||
<li><a href="tutorial-gateway-guide.html">Gateway Guide</a></li>
|
||||
<li><a href="tutorial-listing-xrp.html">Listing XRP as an Exchange</a></li>
|
||||
<li><a href="tutorial-escrow.html">Escrow Tutorials</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Features <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="concept-accounts.html">Accounts</a></li>
|
||||
<li><a href="concept-amendments.html">Amendments</a></li>
|
||||
<li><a href="concept-consensus.html">Consensus Process</a></li>
|
||||
<li><a href="concept-reaching-consensus.html">Reaching Consensus in the XRP Ledger</a></li>
|
||||
<li><a href="concept-fee-voting.html">Fee Voting</a></li>
|
||||
<li><a href="concept-fees.html">Fees (Disambiguation)</a></li>
|
||||
<li><a href="concept-freeze.html">Freeze</a></li>
|
||||
<li><a href="concept-partial-payments.html">Partial Payments</a></li>
|
||||
<li><a href="concept-paths.html">Paths</a></li>
|
||||
<li><a href="concept-reserves.html">Reserves</a></li>
|
||||
<li><a href="concept-stand-alone-mode.html">Stand-Alone Mode</a></li>
|
||||
<li><a href="concept-transaction-cost.html">Transaction Cost</a></li>
|
||||
<li><a href="concept-transfer-fees.html">Transfer Fees</a></li>
|
||||
<li><a href="concept-noripple.html">Understanding the NoRipple flag</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Gateway Bulletins <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="gb-2015-06.html">GB-2015-06: Corrections to Autobridging</a></li>
|
||||
<li><a href="gb-2015-05.html">GB-2015-05: Historical Ledger Query Migration</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">API Tools <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="ripple-api-tool.html">WebSocket API Tool</a></li>
|
||||
<li><a href="data-api-v2-tool.html">Data API v2 Tool</a></li>
|
||||
<li><a href="tool-jsonrpc.html">rippled JSON-RPC Tool</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li><a href="https://github.com/ripple/ripple-dev-portal" title="GitHub">Site Source</a></li>
|
||||
</ul><!-- /#dev-menu -->
|
||||
</div><!-- /.subnav .container -->
|
||||
</div><!-- /.subnav -->
|
||||
</header>
|
||||
|
||||
|
||||
<div class="wrap container" role="document">
|
||||
<aside class="sidebar" role="complementary">
|
||||
<div class="dev_nav_wrapper">
|
||||
<div id="cont">
|
||||
<h5>In this category:</h5>
|
||||
<ul class="dev_nav_sidebar">
|
||||
<li class="level-1"><a href="index.html">Category: Tutorials</a></li>
|
||||
<li class="level-2"><a href="tutorial-multisign.html">How to Multi-Sign</a></li>
|
||||
<li class="level-2"><a href="tutorial-paychan.html">Payment Channels Tutorial</a></li>
|
||||
<li class="level-2"><a href="concept-issuing-and-operational-addresses.html">Issuing and Operational Addresses</a></li>
|
||||
<li class="level-2"><a href="tutorial-reliable-transaction-submission.html">Reliable Transaction Submission</a></li>
|
||||
<li class="level-2"><a href="tutorial-rippleapi-beginners-guide.html">RippleAPI Beginners Guide</a></li>
|
||||
<li class="level-2"><a href="tutorial-rippled-setup.html">rippled Setup</a></li>
|
||||
<li class="level-2"><a href="tutorial-gateway-guide.html">Gateway Guide</a></li>
|
||||
<li class="level-2"><a href="tutorial-listing-xrp.html">Listing XRP as an Exchange</a></li>
|
||||
<li class="level-2"><a href="tutorial-escrow.html">Escrow Tutorials</a></li>
|
||||
</ul>
|
||||
<hr />
|
||||
<h5>In this page:</h5>
|
||||
<ul class="dev_nav_sidebar" id="dactyl_toc_sidebar">
|
||||
<li class="level-1"><a href="#payment-channels-tutorial">Payment Channels Tutorial</a></li>
|
||||
<li class="level-2"><a href="#background">Background</a></li>
|
||||
<li class="level-2"><a href="#example-values">Example Values</a></li>
|
||||
<li class="level-2"><a href="#flow-diagram">Flow Diagram</a></li>
|
||||
<li class="level-2"><a href="#1-the-payer-creates-a-payment-channel-to-a-particular-recipient">1. The payer creates a payment channel to a particular recipient.</a></li>
|
||||
<li class="level-2"><a href="#2-the-payee-checks-specifics-of-the-payment-channel">2. The payee checks specifics of the payment channel.</a></li>
|
||||
<li class="level-2"><a href="#3-the-payer-creates-one-or-more-signed-claims-for-the-xrp-in-the-channel">3. The payer creates one or more signed claims for the XRP in the channel.</a></li>
|
||||
<li class="level-2"><a href="#4-the-payer-sends-a-claim-to-the-payee-as-payment-for-goods-or-services">4. The payer sends a claim to the payee as payment for goods or services.</a></li>
|
||||
<li class="level-2"><a href="#5-the-payee-verifies-the-claims">5. The payee verifies the claims.</a></li>
|
||||
<li class="level-2"><a href="#6-payee-provides-goods-or-services">6. Payee provides goods or services.</a></li>
|
||||
<li class="level-2"><a href="#7-repeat-steps-3-6-as-desired">7. Repeat steps 3-6 as desired.</a></li>
|
||||
<li class="level-2"><a href="#8-when-ready-the-payee-redeems-a-claim-for-the-authorized-amount">8. When ready, the payee redeems a claim for the authorized amount.</a></li>
|
||||
<li class="level-2"><a href="#9-when-the-payer-and-payee-are-done-doing-business-the-payer-requests-for-the-channel-to-be-closed">9. When the payer and payee are done doing business, the payer requests for the channel to be closed.</a></li>
|
||||
<li class="level-2"><a href="#10-anyone-can-close-the-expired-channel">10. Anyone can close the expired channel.</a></li>
|
||||
<li class="level-2"><a href="#conclusion">Conclusion</a></li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
<main class="main" role="main">
|
||||
<div class='content'>
|
||||
<h1 id="payment-channels-tutorial">Payment Channels Tutorial</h1>
|
||||
<p>Payment Channels are an advanced feature for sending "asynchronous" XRP payments that can be divided into very small increments and settled later. This tutorial walks through the entire process of using a payment channel, with examples using the <a href="reference-rippled.html">JSON-RPC API</a> of a local <code>rippled</code> server.</p>
|
||||
<h2 id="background">Background</h2>
|
||||
<p>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 is doing business on the XRP Ledger (XRP Ledger), receiving XRP as payment for goods or services.</p>
|
||||
<p>The types of goods and services are not defined by the software or in this tutorial. However, the types of goods and services that are a good fit for payment channels are:</p>
|
||||
<ul>
|
||||
<li>Things that can be transmitted near-instantly, like digital items</li>
|
||||
<li>Inexpensive things, where the cost of processing a transaction is a non-trivial portion of the price</li>
|
||||
<li>Things normally bought in bulk, where the exact quantity desired is not known in advance</li>
|
||||
</ul>
|
||||
<p>Ideally, to step through this tutorial, you would have two people, each with the keys to a <a href="concept-accounts.html">funded XRP Ledger account</a>. However, you can also step through the tutorial as one person managing two XRP Ledger addresses.</p>
|
||||
<h2 id="example-values">Example Values</h2>
|
||||
<p>The example addresses used in this tutorial are:</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><strong>Payer's address</strong></td>
|
||||
<td>rN7n7otQDd6FczFgLdSqtcsAUxDkw6fzRH</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Public key used for channel (in base58)</strong></td>
|
||||
<td>aB44YfzW24VDEJQ2UuLPV2PvqcPCSoLnL7y5M1EzhdW4LnK5xMS3</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Public key used for channel (in hex)</strong></td>
|
||||
<td>023693F15967AE357D0327974AD46FE3C127113B1110D6044FD41E723689F81CC6</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Payee's address</strong></td>
|
||||
<td>rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p class="devportal-callout tip"><strong>Tip:</strong> In this example, the channel's public key is the public key from the payer's master key pair. This is perfectly safe and valid. It is also perfectly safe and valid to use a different key pair, as long as only the payer knows the public and secret keys for that key pair. <!-- Editor's note: We don't have a good page to link to explain key pairs as of time of this writing. --></p>
|
||||
<p>Additionally, you'll need a <code>rippled</code> server to send transactions to. The examples in this tutorial assume a <code>rippled</code> server is running on the test machine (<code>localhost</code>) with an unencrypted JSON-RPC API endpoint on port <strong>5005</strong>.</p>
|
||||
<p>To test without transferring real XRP, you can use <a href="https://ripple.com/build/ripple-test-net/">Ripple Test Net</a> addresses with Test Net XRP. If you do use the Ripple Test Net, you can use the Test Net servers' JSON-RPC API by connecting to <code>https://api.altnet.rippletest.net:51234</code> instead of <code>http://localhost:5005/</code>.</p>
|
||||
<p>You can use any amount of XRP for the payment channels. The example values in this tutorial set aside 100 XRP (<code>100000000</code> drops) in a payment channel for at least 1 day.</p>
|
||||
<h2 id="flow-diagram">Flow Diagram</h2>
|
||||
<p>The following diagram summarizes the lifecycle of a payment channel:</p>
|
||||
<p><a href="img/paychan-flow.png"><img alt="Payment Channel Flow Diagram" src="img/paychan-flow.png"/></a></p>
|
||||
<p>You can match up the numbered steps in this diagram with the steps of this tutorial.</p>
|
||||
<ol>
|
||||
<li><a href="#1-the-payer-creates-a-payment-channel-to-a-particular-recipient">Payer: Create channel</a></li>
|
||||
<li><a href="#2-the-payee-checks-specifics-of-the-payment-channel">Payee: Check channel</a></li>
|
||||
<li><a href="#3-the-payer-creates-one-or-more-signed-claims-for-the-xrp-in-the-channel">Payer: Sign claims</a></li>
|
||||
<li><a href="#4-the-payer-sends-a-claim-to-the-payee-as-payment-for-goods-or-services">Payer: Send claim(s) to payee</a></li>
|
||||
<li><a href="#5-the-payee-verifies-the-claims">Payee: Verify claims</a></li>
|
||||
<li><a href="#6-payee-provides-goods-or-services">Payee: Provide goods or services</a></li>
|
||||
<li><a href="#7-repeat-steps-3-6-as-desired">Repeat steps 3-6 as desired</a></li>
|
||||
<li><a href="#8-when-ready-the-payee-redeems-a-claim-for-the-authorized-amount">Payee: Redeem claim</a></li>
|
||||
<li><a href="#9-when-the-payer-and-payee-are-done-doing-business-the-payer-requests-for-the-channel-to-be-closed">Payer: Request to close channel</a></li>
|
||||
<li><a href="#10-anyone-can-close-the-expired-channel">Payer (or anyone else): Close expired channel</a></li>
|
||||
</ol>
|
||||
<h2 id="1-the-payer-creates-a-payment-channel-to-a-particular-recipient">1. The payer creates a payment channel to a particular recipient.</h2>
|
||||
<p>This is a <a href="reference-transaction-format.html#paymentchannelcreate">PaymentChannelCreate transaction</a>. As part of this process, the payer sets certain specifics of the channel like an expiration time and a settlement delay, which affect the guarantees around the claims in the channel. The payer also sets the public key that will be used to verify claims against the channel.</p>
|
||||
<p class="devportal-callout tip"><strong>Tip:</strong> The "settlement delay" does not delay the settlement, which can happen as fast as a ledger version closes (3-5 seconds). The "settlement delay" is a forced delay on closing the channel so that the payee has a chance to finish with settlement.</p>
|
||||
<p>The following example shows creation of a payment channel by <a href="reference-rippled.html#sign-and-submit-mode">submitting</a> to a local <code>rippled</code> server with the JSON-RPC API. The payment channel allocates 100 XRP from the <a href="#example-values">example payer</a> (rN7n7...) to the <a href="#example-values">example payee</a> (rf1Bi...) with a settlement delay of 1 day. The public key is the example payer's master public key, in hexadecimal.</p>
|
||||
<p>Request:</p>
|
||||
<pre><code>POST http://localhost:5005/
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"method": "submit",
|
||||
"params": [{
|
||||
"secret": "s████████████████████████████",
|
||||
"tx_json": {
|
||||
"Account": "rN7n7otQDd6FczFgLdSqtcsAUxDkw6fzRH",
|
||||
"TransactionType": "PaymentChannelCreate",
|
||||
"Amount": "100000000",
|
||||
"Destination": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"SettleDelay": 86400,
|
||||
"PublicKey": "023693F15967AE357D0327974AD46FE3C127113B1110D6044FD41E723689F81CC6",
|
||||
"DestinationTag": 20170428
|
||||
},
|
||||
"fee_mult_max": 1000
|
||||
}]
|
||||
}
|
||||
</code></pre>
|
||||
<p>Response:</p>
|
||||
<pre><code>200 OK
|
||||
|
||||
{
|
||||
"result": {
|
||||
"engine_result": "tesSUCCESS",
|
||||
"engine_result_code": 0,
|
||||
"engine_result_message": "The transaction was applied. Only final in a validated ledger.",
|
||||
...
|
||||
"tx_json": {
|
||||
...
|
||||
"TransactionType": "PaymentChannelCreate",
|
||||
"hash": "3F93C482C0BC2A1387D9E67DF60BECBB76CC2160AE98522C77AF0074D548F67D"
|
||||
}
|
||||
}
|
||||
}
|
||||
</code></pre>
|
||||
<p>The immediate response to the <code>submit</code> request contains a <em>provisional</em> result with the transaction's identifying <code>hash</code> value. The payer should check the transaction's <em>final</em> result in a validated ledger and get the Channel ID from the metadata. This can be done with the <code>tx</code> command:</p>
|
||||
<p>Request:</p>
|
||||
<pre><code>POST http://localhost:5005/
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"method": "tx",
|
||||
"params": [{
|
||||
"transaction": "3F93C482C0BC2A1387D9E67DF60BECBB76CC2160AE98522C77AF0074D548F67D"
|
||||
}]
|
||||
}
|
||||
</code></pre>
|
||||
<p>Response:</p>
|
||||
<pre><code>200 OK
|
||||
|
||||
{
|
||||
"result": {
|
||||
"Account": "rN7n7otQDd6FczFgLdSqtcsAUxDkw6fzRH",
|
||||
"Amount": "100000000",
|
||||
"Destination": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
...
|
||||
"TransactionType": "PaymentChannelCreate",
|
||||
...
|
||||
"hash": "3F93C482C0BC2A1387D9E67DF60BECBB76CC2160AE98522C77AF0074D548F67D",
|
||||
"inLedger": 29380080,
|
||||
"ledger_index": 29380080,
|
||||
"meta": {
|
||||
"AffectedNodes": [
|
||||
...
|
||||
{
|
||||
"CreatedNode": {
|
||||
"LedgerEntryType": "PayChannel",
|
||||
"LedgerIndex": "5DB01B7FFED6B67E6B0414DED11E051D2EE2B7619CE0EAA6286D67A3A4D5BDB3",
|
||||
"NewFields": {
|
||||
"Account": "rN7n7otQDd6FczFgLdSqtcsAUxDkw6fzRH",
|
||||
"Amount": "100000000",
|
||||
"Destination": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"DestinationTag": 20170428,
|
||||
"PublicKey": "023693F15967AE357D0327974AD46FE3C127113B1110D6044FD41E723689F81CC6",
|
||||
"SettleDelay": 86400
|
||||
}
|
||||
}
|
||||
},
|
||||
...
|
||||
],
|
||||
"TransactionIndex": 16,
|
||||
"TransactionResult": "tesSUCCESS"
|
||||
},
|
||||
"status": "success",
|
||||
"validated": true
|
||||
}
|
||||
}
|
||||
</code></pre>
|
||||
<p>In the response from the JSON-RPC, the payer should look for the following:</p>
|
||||
<ul>
|
||||
<li>In the transaction's <code>meta</code> field, confirm that the <code>TransactionResult</code> is <code>tesSUCCESS</code>.</li>
|
||||
<li>Confirm that the response has <code>"validated":true</code> to indicate the data comes from a validated ledger. (The result <code>tesSUCCESS</code> is only <a href="reference-transaction-format.html#finality-of-results">final</a> if it appears in a validated ledger version.)</li>
|
||||
<li>In the <code>AffectedNodes</code> array of the transaction's <code>meta</code> field, look for a <code>CreatedNode</code> object with the <code>LedgerEntryType</code> of <code>PayChannel</code>. The <code>LedgerIndex</code> field of the <code>CreatedNode</code> object indicates the Channel ID. (In the above example, this is a hex string starting with "5DB0...") The Channel ID is necessary later to sign claims.
|
||||
For more information on the PayChannel ledger object type, see <a href="reference-ledger-format.html#paychannel">PayChannel ledger node type</a>.</li>
|
||||
</ul>
|
||||
<h2 id="2-the-payee-checks-specifics-of-the-payment-channel">2. The payee checks specifics of the payment channel.</h2>
|
||||
<p>You can look up payment channels with the <a href="reference-rippled.html#account-channels"><code>account_channels</code> API method</a>, using the payer of the channel, as in the following example (using the JSON-RPC API):</p>
|
||||
<p>Request:</p>
|
||||
<pre><code>POST http://localhost:5005/
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"method": "account_channels",
|
||||
"params": [{
|
||||
"account": "rN7n7otQDd6FczFgLdSqtcsAUxDkw6fzRH",
|
||||
"destination_account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"ledger_index": "validated"
|
||||
}]
|
||||
}
|
||||
</code></pre>
|
||||
<p>Response:</p>
|
||||
<pre><code>200 OK
|
||||
|
||||
{
|
||||
"result": {
|
||||
"account": "rN7n7otQDd6FczFgLdSqtcsAUxDkw6fzRH",
|
||||
"channels": [{
|
||||
"account": "rN7n7otQDd6FczFgLdSqtcsAUxDkw6fzRH",
|
||||
"amount": "100000000",
|
||||
"balance": "0",
|
||||
"channel_id": "5DB01B7FFED6B67E6B0414DED11E051D2EE2B7619CE0EAA6286D67A3A4D5BDB3",
|
||||
"destination_account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"destination_tag": 20170428,
|
||||
"public_key": "aB44YfzW24VDEJQ2UuLPV2PvqcPCSoLnL7y5M1EzhdW4LnK5xMS3",
|
||||
"public_key_hex": "023693F15967AE357D0327974AD46FE3C127113B1110D6044FD41E723689F81CC6",
|
||||
"settle_delay": 86400
|
||||
}],
|
||||
"status": "success"
|
||||
}
|
||||
}
|
||||
</code></pre>
|
||||
<p>The payee should check that the parameters of the payment channel are suitable for their specific use case, including all of the following:</p>
|
||||
<ul>
|
||||
<li>Confirm the <code>destination_account</code> field has the payee's correct address.</li>
|
||||
<li>Confirm the <code>settle_delay</code> field has a settlement delay in seconds that provides enough time for the payee to redeem outstanding claims.</li>
|
||||
<li>Confirm the fields <code>cancel_after</code> (immutable expiration) and <code>expiration</code> (mutable expiration), if they are present, are not too soon. The payee should take note of these times so they can be sure to redeem claims before then.</li>
|
||||
<li>Take note of the <code>public_key</code> and <code>channel_id</code> fields. These are necessary later to verify and redeem claims.</li>
|
||||
<li><em>(Optional)</em> Confirm the <code>destination_tag</code> field is present and has a desired destination tag.</li>
|
||||
</ul>
|
||||
<p>Since there can be multiple channels between the same two parties, it is important for the payee to check the qualities of the correct channel. If there is any chance of confusion, the payer should clarify the Channel ID (<code>channel_id</code>) of the channel to use.</p>
|
||||
<h2 id="3-the-payer-creates-one-or-more-signed-claims-for-the-xrp-in-the-channel">3. The payer creates one or more signed <em>claims</em> for the XRP in the channel.</h2>
|
||||
<p>The amounts of these claims depends on the specific goods or services the payer wants to pay for.</p>
|
||||
<p>Each claim must be for a cumulative amount. In other words, to purchase two items at 10 XRP each, the first claim should have an amount of 10 XRP and the second claim should have an amount of 20 XRP. The claim can never be more than the total amount of XRP allocated to the channel. (A <a href="reference-transaction-format.html#paymentchannelfund">PaymentChannelFund</a> transaction can increase the total amount of XRP allocated to the channel.)</p>
|
||||
<p>You can create claims with the <a href="reference-rippled.html#channel-authorize"><code>channel_authorize</code> API method</a>. The following example authorizes 1 XRP from the channel:</p>
|
||||
<p>Request:</p>
|
||||
<pre><code>POST http://localhost:5005/
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"method": "channel_authorize",
|
||||
"params": [{
|
||||
"channel_id": "5DB01B7FFED6B67E6B0414DED11E051D2EE2B7619CE0EAA6286D67A3A4D5BDB3",
|
||||
"secret": "s████████████████████████████",
|
||||
"amount": "1000000"
|
||||
}]
|
||||
}
|
||||
</code></pre>
|
||||
<p>Response:</p>
|
||||
<pre><code>{
|
||||
"result": {
|
||||
"signature": "304402204EF0AFB78AC23ED1C472E74F4299C0C21F1B21D07EFC0A3838A420F76D783A400220154FB11B6F54320666E4C36CA7F686C16A3A0456800BBC43746F34AF50290064",
|
||||
"status": "success"
|
||||
}
|
||||
}
|
||||
</code></pre>
|
||||
<h2 id="4-the-payer-sends-a-claim-to-the-payee-as-payment-for-goods-or-services">4. The payer sends a claim to the payee as payment for goods or services.</h2>
|
||||
<p>This communication happens "off-ledger" in any communication system the payer and payee can agree to. You should use secure communications for this, but it's not strictly necessary. Only the payer or payee of a channel can redeem claims against that channel.</p>
|
||||
<p>The exact format of the claim is not important as long as it communicates the following information:</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th align="left">Field</th>
|
||||
<th align="left">Example</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td align="left">Channel ID</td>
|
||||
<td align="left"><code>5DB01B7FFED6B67E6B0414DED11E051D2EE2B7619CE0EAA6286D67A3A4D5BDB3</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left">Amount of XRP, in drops</td>
|
||||
<td align="left"><code>1000000</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left">Signature</td>
|
||||
<td align="left"><code>304402204EF0AFB78AC23ED1C472E74F4299C0C21F1B21D07EFC0A3838A420F76D783A</code> <br/> <code>400220154FB11B6F54320666E4C36CA7F686C16A3A0456800BBC43746F34AF50290064</code> <em>(Note: this long string has been broken to fit on one line.)</em></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>The payee also needs to know the Public Key associated with the channel, which is the same throughout the channel's life.</p>
|
||||
<h2 id="5-the-payee-verifies-the-claims">5. The payee verifies the claims.</h2>
|
||||
<p>You can verify claims using the <a href="reference-rippled.html#channel-verify"><code>channel_verify</code> API method</a>. The payee should confirm that the amount of the claim is equal to or greater than the total price of goods and services provided. (Since the amount is cumulative, this is the total price of all goods and services purchased so far.)</p>
|
||||
<p>Example of using <code>channel_verify</code> with the JSON-RPC API:</p>
|
||||
<p>Request:</p>
|
||||
<pre><code>POST http://localhost:5005/
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"method": "channel_verify",
|
||||
"params": [{
|
||||
"channel_id": "5DB01B7FFED6B67E6B0414DED11E051D2EE2B7619CE0EAA6286D67A3A4D5BDB3",
|
||||
"signature": "304402204EF0AFB78AC23ED1C472E74F4299C0C21F1B21D07EFC0A3838A420F76D783A400220154FB11B6F54320666E4C36CA7F686C16A3A0456800BBC43746F34AF50290064",
|
||||
"public_key": "aB44YfzW24VDEJQ2UuLPV2PvqcPCSoLnL7y5M1EzhdW4LnK5xMS3",
|
||||
"amount": "1000000"
|
||||
}]
|
||||
}
|
||||
</code></pre>
|
||||
<p>Response:</p>
|
||||
<pre><code>200 OK
|
||||
|
||||
{
|
||||
"result": {
|
||||
"signature_verified":true,
|
||||
"status":"success"
|
||||
}
|
||||
}
|
||||
</code></pre>
|
||||
<p>If the response shows <code>"signature_verified": true</code> then the claim's signature is genuine. The payee must <strong>also</strong> confirm that the channel has enough XRP available to honor the claim. To do this, the payee makes an <a href="reference-rippled.html#account-channels"><code>account_channels</code> request</a> to confirm the most recent validated state of the payment channel.</p>
|
||||
<p>Request:</p>
|
||||
<pre><code>POST http://localhost:5005/
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"method": "account_channels",
|
||||
"params": [{
|
||||
"account": "rN7n7otQDd6FczFgLdSqtcsAUxDkw6fzRH",
|
||||
"destination_account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"ledger_index": "validated"
|
||||
}]
|
||||
}
|
||||
</code></pre>
|
||||
<p>Response:</p>
|
||||
<pre><code>200 OK
|
||||
|
||||
{
|
||||
"result": {
|
||||
"account": "rN7n7otQDd6FczFgLdSqtcsAUxDkw6fzRH",
|
||||
"channels": [{
|
||||
"account": "rN7n7otQDd6FczFgLdSqtcsAUxDkw6fzRH",
|
||||
"amount": "100000000",
|
||||
"balance": "0",
|
||||
"channel_id": "5DB01B7FFED6B67E6B0414DED11E051D2EE2B7619CE0EAA6286D67A3A4D5BDB3",
|
||||
"destination_account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"destination_tag": 20170428,
|
||||
"public_key": "aB44YfzW24VDEJQ2UuLPV2PvqcPCSoLnL7y5M1EzhdW4LnK5xMS3",
|
||||
"public_key_hex": "023693F15967AE357D0327974AD46FE3C127113B1110D6044FD41E723689F81CC6",
|
||||
"settle_delay": 86400
|
||||
}],
|
||||
"status": "success"
|
||||
}
|
||||
}
|
||||
</code></pre>
|
||||
<p>The payee should check the following:</p>
|
||||
<ul>
|
||||
<li>Find the object in the <code>channels</code> array whose <code>channel_id</code> matches the Channel ID of the claim. It is possible to have multiple payment channels, even between the same parties, but a claim can only be redeemed against the channel with the matching ID.</li>
|
||||
<li>Confirm that the <code>expiration</code> (mutable expiration) of the channel, if present, is not too soon. The payee must redeem claims before this time.</li>
|
||||
<li>Confirm that the <code>amount</code> of the claim is equal or less than the <code>amount</code> of the channel. If the <code>amount</code> of the claim is higher, the claim cannot be redeemed unless the payer uses a <a href="reference-transaction-format.html#paymentchannelfund">PaymentChannelFund transaction</a> to increase the total amount of XRP available to the channel.</li>
|
||||
<li>Confirm that the <code>balance</code> of the channel matches the amount the payee expects to have already received from the channel. If these do not match up, the payee should double-check the channel's transaction history. Some possible explanations for a mismatch include:<ul>
|
||||
<li>The payer used a <a href="reference-transaction-format.html#paymentchannelclaim">PaymentChannelClaim</a> transaction to deliver XRP from the channel to the payee, but the payee did not notice and record the incoming transaction.</li>
|
||||
<li>The payee's records include transactions that are "in flight" or have not yet been included in the latest validated ledger version. The payee can use the <a href="reference-rippled.html#tx"><code>tx</code> command</a> to look up the state of individual transactions to check this.</li>
|
||||
<li>The <code>account_channels</code> request did not specify the correct ledger version. (Use <code>"ledger_index": "validated"</code> to get the latest validated ledger version)</li>
|
||||
<li>The payee previously redeemed XRP but forgot to record it.</li>
|
||||
<li>The payee attempted to redeem XRP and recorded the tentative result, but the transaction's final validated result was not the same and the payee neglected to record the final validated result.</li>
|
||||
<li>The <code>rippled</code> server the payee queried has lost sync with the rest of the network or is experiencing an unknown bug. Use the <a href="reference-rippled.html#server-info"><code>server_info</code> command</a> to check the state of the server. (If you can reproduce this situation, please <a href="https://github.com/ripple/rippled/issues/">report an issue</a>.)</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<p>After confirming both the signature and the current state of the payment channel, the payee has not yet received the XRP, but is certain that he or she <em>can</em> redeem the XRP as long as the transaction to do so is processed before the channel expires.</p>
|
||||
<h2 id="6-payee-provides-goods-or-services">6. Payee provides goods or services.</h2>
|
||||
<p>At this point, the payee can provide goods and services to the payer, knowing that payment is already assured.</p>
|
||||
<p>For purposes of this tutorial, the payee can give the payer a high-five or equivalent online message as the "goods and services".</p>
|
||||
<h2 id="7-repeat-steps-3-6-as-desired">7. Repeat steps 3-6 as desired.</h2>
|
||||
<p>The payer and payee can repeat steps 3 through 6 (creating, transmitting, and verifying claims in exchange for goods and services) as many times and as often as they like without waiting for the XRP Ledger itself. The two main limits of this process are:</p>
|
||||
<ul>
|
||||
<li>
|
||||
<p>The amount of XRP in the payment channel. (If necessary, the payer can send a <a href="reference-transaction-format.html#paymentchannelfund">PaymentChannelFund transaction</a> to increase the total amount of XRP available to the channel.)</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>The immutable expiration of the payment channel, if one is set. (The <code>cancel_after</code> field in the <a href="reference-rippled.html#account-channels"><code>account_channels</code></a> response shows this.)</p>
|
||||
</li>
|
||||
</ul>
|
||||
<h2 id="8-when-ready-the-payee-redeems-a-claim-for-the-authorized-amount">8. When ready, the payee redeems a claim for the authorized amount.</h2>
|
||||
<p>This is the point where the payee finally receives some XRP from the channel.</p>
|
||||
<p>This is a <a href="reference-transaction-format.html#paymentchannelclaim">PaymentChannelClaim transaction</a> with the <code>Balance</code>, <code>Amount</code>, <code>Signature</code>, and <code>PublicKey</code> fields provided. Because claim values are cumulative, the payee only needs to redeem the largest (most recent) claim to get the full amount. The payee is not required to redeem the claim for the full amount authorized.</p>
|
||||
<p>The payee can do this multiple times, to settle partially while still doing business, if desired.</p>
|
||||
<p>Example of claiming XRP from a channel:</p>
|
||||
<p>Request:</p>
|
||||
<pre><code>POST http://localhost:5005/
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"method": "submit",
|
||||
"params": [{
|
||||
"secret": "s████████████████████████████",
|
||||
"tx_json": {
|
||||
"Account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"TransactionType": "PaymentChannelClaim",
|
||||
"Amount": "1000000",
|
||||
"Balance": "1000000",
|
||||
"Channel": "5DB01B7FFED6B67E6B0414DED11E051D2EE2B7619CE0EAA6286D67A3A4D5BDB3",
|
||||
"PublicKey": "023693F15967AE357D0327974AD46FE3C127113B1110D6044FD41E723689F81CC6",
|
||||
"Signature": "304402204EF0AFB78AC23ED1C472E74F4299C0C21F1B21D07EFC0A3838A420F76D783A400220154FB11B6F54320666E4C36CA7F686C16A3A0456800BBC43746F34AF50290064"
|
||||
},
|
||||
"fee_mult_max": 1000
|
||||
}]
|
||||
}
|
||||
</code></pre>
|
||||
<p>Response:</p>
|
||||
<pre><code>200 OK
|
||||
|
||||
{
|
||||
"result": {
|
||||
"engine_result": "tesSUCCESS",
|
||||
"engine_result_code": 0,
|
||||
"engine_result_message": "The transaction was applied. Only final in a validated ledger.",
|
||||
"status": "success",
|
||||
"tx_blob": "12000F2280000000240000017450165DB01B7FFED6B67E6B0414DED11E051D2EE2B7619CE0EAA6286D67A3A4D5BDB36140000000000F42406240000000000F424068400000000000000A7121023693F15967AE357D0327974AD46FE3C127113B1110D6044FD41E723689F81CC6732103AB40A0490F9B7ED8DF29D246BF2D6269820A0EE7742ACDD457BEA7C7D0931EDB7447304502210096B933BC24DA77D8C4057B4780B282BA66C668DFE1ACF4EEC063AD6661725797022037C8823669CE91AACA8CC754C9F041359F85B0B32384AEA141EBC3603798A24C7646304402204EF0AFB78AC23ED1C472E74F4299C0C21F1B21D07EFC0A3838A420F76D783A400220154FB11B6F54320666E4C36CA7F686C16A3A0456800BBC43746F34AF5029006481144B4E9C06F24296074F7BC48F92A97916C6DC5EA9",
|
||||
"tx_json": {
|
||||
"Account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"Amount": "1000000",
|
||||
"Balance": "1000000",
|
||||
"Channel": "5DB01B7FFED6B67E6B0414DED11E051D2EE2B7619CE0EAA6286D67A3A4D5BDB3",
|
||||
"Fee": "10",
|
||||
"Flags": 2147483648,
|
||||
"PublicKey": "023693F15967AE357D0327974AD46FE3C127113B1110D6044FD41E723689F81CC6",
|
||||
"Sequence": 372,
|
||||
"Signature": "304402204EF0AFB78AC23ED1C472E74F4299C0C21F1B21D07EFC0A3838A420F76D783A400220154FB11B6F54320666E4C36CA7F686C16A3A0456800BBC43746F34AF50290064",
|
||||
"SigningPubKey": "03AB40A0490F9B7ED8DF29D246BF2D6269820A0EE7742ACDD457BEA7C7D0931EDB",
|
||||
"TransactionType": "PaymentChannelClaim",
|
||||
"TxnSignature": "304502210096B933BC24DA77D8C4057B4780B282BA66C668DFE1ACF4EEC063AD6661725797022037C8823669CE91AACA8CC754C9F041359F85B0B32384AEA141EBC3603798A24C",
|
||||
"hash": "C9FE08FC88CF76C3B06622ADAA47AE99CABB3380E4D195E7751274CFD87910EB"
|
||||
}
|
||||
}
|
||||
}
|
||||
</code></pre>
|
||||
<p>The payee should confirm that this transaction is successful in a validated ledger. For the full details, see <a href="tutorial-reliable-transaction-submission.html">Reliable Transaction Submission</a>.</p>
|
||||
<h2 id="9-when-the-payer-and-payee-are-done-doing-business-the-payer-requests-for-the-channel-to-be-closed">9. When the payer and payee are done doing business, the payer requests for the channel to be closed.</h2>
|
||||
<p>This is a <a href="reference-transaction-format.html#paymentchannelclaim">PaymentChannelClaim transaction</a> with the <code>tfClose</code> flag set, or a <a href="reference-transaction-format.html#paymentchannelfund">PaymentChannelFund transaction</a> with the <code>Expiration</code> field set. <em>(9a in the <a href="#flow-diagram">flow diagram</a>)</em>.</p>
|
||||
<p>If the channel has no XRP remaining in it when the payer requests to close the channel, it closes immediately.</p>
|
||||
<p>If the channel <em>does</em> have XRP remaining, the request to close a channel acts as a final warning to the payee to redeem any outstanding claims right away. The payee has an amount of time no less than the settlement delay before the channel is closed. The exact number of seconds varies slightly based on the close times of ledgers.</p>
|
||||
<p>The payee can also close a payment channel immediately after processing a claim <em>(9b in the <a href="#flow-diagram">flow diagram</a>)</em>.</p>
|
||||
<p>Example of <a href="reference-rippled.html#sign-and-submit-mode">submitting a transaction</a> requesting a channel to close:</p>
|
||||
<pre><code>{
|
||||
"method": "submit",
|
||||
"params": [{
|
||||
"secret": "s████████████████████████████",
|
||||
"tx_json": {
|
||||
"Account": "rN7n7otQDd6FczFgLdSqtcsAUxDkw6fzRH",
|
||||
"TransactionType": "PaymentChannelClaim",
|
||||
"Channel": "5DB01B7FFED6B67E6B0414DED11E051D2EE2B7619CE0EAA6286D67A3A4D5BDB3",
|
||||
"Flags": 2147614720
|
||||
},
|
||||
"fee_mult_max": 1000
|
||||
}]
|
||||
}
|
||||
</code></pre>
|
||||
<p>After the transaction is included in a validated ledger, either party can look up the currently-scheduled expiration of the channel using the <a href="reference-rippled.html#account-channels"><code>account_channels</code> method</a>. Be sure to specify <code>"ledger_index": "validated"</code> to get data from the latest validated ledger version.</p>
|
||||
<p>Example <code>account_channels</code> response:</p>
|
||||
<pre><code>{
|
||||
"result": {
|
||||
"account": "rN7n7otQDd6FczFgLdSqtcsAUxDkw6fzRH",
|
||||
"channels": [
|
||||
{
|
||||
"account": "rN7n7otQDd6FczFgLdSqtcsAUxDkw6fzRH",
|
||||
"amount": "100000000",
|
||||
"balance": "1000000",
|
||||
"channel_id": "5DB01B7FFED6B67E6B0414DED11E051D2EE2B7619CE0EAA6286D67A3A4D5BDB3",
|
||||
"destination_account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"destination_tag": 20170428,
|
||||
"expiration": 547073182,
|
||||
"public_key": "aB44YfzW24VDEJQ2UuLPV2PvqcPCSoLnL7y5M1EzhdW4LnK5xMS3",
|
||||
"public_key_hex": "023693F15967AE357D0327974AD46FE3C127113B1110D6044FD41E723689F81CC6",
|
||||
"settle_delay": 86400
|
||||
}
|
||||
],
|
||||
"status": "success"
|
||||
}
|
||||
}
|
||||
</code></pre>
|
||||
<p>In this example, the <code>expiration</code> value 547073182 in <a href="reference-rippled.html#specifying-time">seconds since the Ripple Epoch</a> maps to 2017-05-02T20:46:22Z, so any claims not redeemed by that time are no longer valid.</p>
|
||||
<h2 id="10-anyone-can-close-the-expired-channel">10. Anyone can close the expired channel.</h2>
|
||||
<p>After the settlement delay has passed or the channel has reached its planned expiration time, the channel is expired. Any further transaction that would affect the channel can only close it, returning unclaimed XRP to the payer.</p>
|
||||
<p>The channel can remain on the ledger in an expired state indefinitely. This is because the ledger cannot change except as the results of a transaction, so <em>someone</em> must send a transaction to cause the expired channel to close. As long as the channel remains on the ledger, it counts as an object owned by the payer for purposes of the <a href="concept-reserves.html#owner-reserves">owner reserve</a>.</p>
|
||||
<p>Ripple recommends that the payer sends a second <a href="reference-transaction-format.html#paymentchannelclaim">PaymentChannelClaim transaction</a> with the <code>tfClose</code> flag for this purpose. However, other accounts, even those not involved in the payment channel, can cause an expired channel to close.</p>
|
||||
<p>The command to submit the transaction is identical to the previous example requesting channel expiration. (However, its resulting <a href="reference-transaction-format.html#auto-fillable-fields">auto-filled</a> <code>Sequence</code> number, signature, and identifying hash are unique.)</p>
|
||||
<p>Example of <a href="reference-rippled.html#sign-and-submit-mode">submitting</a> a transaction to close an expired channel:</p>
|
||||
<pre><code>{
|
||||
"method": "submit",
|
||||
"params": [{
|
||||
"secret": "s████████████████████████████",
|
||||
"tx_json": {
|
||||
"Account": "rN7n7otQDd6FczFgLdSqtcsAUxDkw6fzRH",
|
||||
"TransactionType": "PaymentChannelClaim",
|
||||
"Channel": "5DB01B7FFED6B67E6B0414DED11E051D2EE2B7619CE0EAA6286D67A3A4D5BDB3",
|
||||
"Flags": 2147614720
|
||||
},
|
||||
"fee_mult_max": 1000
|
||||
}]
|
||||
}
|
||||
</code></pre>
|
||||
<p>When the transaction has been included in a validated ledger, you can look at the metadata of the transaction to confirm that it deleted the channel and returned the XRP to the sender.</p>
|
||||
<p>Example response from using the <a href="reference-rippled.html#tx"><code>tx</code> command</a> to look up the transaction from this step:</p>
|
||||
<pre><code>{
|
||||
"result": {
|
||||
"Account": "rN7n7otQDd6FczFgLdSqtcsAUxDkw6fzRH",
|
||||
"Channel": "5DB01B7FFED6B67E6B0414DED11E051D2EE2B7619CE0EAA6286D67A3A4D5BDB3",
|
||||
"Fee": "5606",
|
||||
"Flags": 2147614720,
|
||||
"Sequence": 41,
|
||||
"SigningPubKey": "023693F15967AE357D0327974AD46FE3C127113B1110D6044FD41E723689F81CC6",
|
||||
"TransactionType": "PaymentChannelClaim",
|
||||
"TxnSignature": "3044022008922FEB6F7D35D42006685BCBB007103D2A40AFAA69A7CFC10DF529F94BB6A402205D67816F50BBAEE0A2709AA3A93707304EC21133550FD2FF7436AD0C3CA6CE27",
|
||||
"date": 547091262,
|
||||
"hash": "9C0CAAC3DD1A74461132DA4451F9E53BDF4C93DFDBEFCE1B10021EC569013B33",
|
||||
"inLedger": 29480670,
|
||||
"ledger_index": 29480670,
|
||||
"meta": {
|
||||
"AffectedNodes": [
|
||||
{
|
||||
"ModifiedNode": {
|
||||
"LedgerEntryType": "AccountRoot",
|
||||
"LedgerIndex": "13F1A95D7AAB7108D5CE7EEAF504B2894B8C674E6D68499076441C4837282BF8",
|
||||
"PreviousTxnID": "C9FE08FC88CF76C3B06622ADAA47AE99CABB3380E4D195E7751274CFD87910EB",
|
||||
"PreviousTxnLgrSeq": 29385089
|
||||
}
|
||||
},
|
||||
{
|
||||
"DeletedNode": {
|
||||
"FinalFields": {
|
||||
"Account": "rN7n7otQDd6FczFgLdSqtcsAUxDkw6fzRH",
|
||||
"Amount": "100000000",
|
||||
"Balance": "1000000",
|
||||
"Destination": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"DestinationTag": 20170428,
|
||||
"Expiration": 547073182,
|
||||
"Flags": 0,
|
||||
"OwnerNode": "0000000000000000",
|
||||
"PreviousTxnID": "C5C70B2BCC515165B7F62ACC8126F8F8B655EB6E1D949A49B2358262BDA986B4",
|
||||
"PreviousTxnLgrSeq": 29451256,
|
||||
"PublicKey": "023693F15967AE357D0327974AD46FE3C127113B1110D6044FD41E723689F81CC6",
|
||||
"SettleDelay": 86400
|
||||
},
|
||||
"LedgerEntryType": "PayChannel",
|
||||
"LedgerIndex": "5DB01B7FFED6B67E6B0414DED11E051D2EE2B7619CE0EAA6286D67A3A4D5BDB3"
|
||||
}
|
||||
},
|
||||
{
|
||||
"ModifiedNode": {
|
||||
"FinalFields": {
|
||||
"Account": "rN7n7otQDd6FczFgLdSqtcsAUxDkw6fzRH",
|
||||
"Balance": "1041862844",
|
||||
"Flags": 0,
|
||||
"OwnerCount": 2,
|
||||
"Sequence": 42
|
||||
},
|
||||
"LedgerEntryType": "AccountRoot",
|
||||
"LedgerIndex": "B1CB040A17F9469BC00376EC8719535655824AD16CB5F539DD5765FEA88FDBE3",
|
||||
"PreviousFields": {
|
||||
"Balance": "942868450",
|
||||
"OwnerCount": 3,
|
||||
"Sequence": 41
|
||||
},
|
||||
"PreviousTxnID": "C5C70B2BCC515165B7F62ACC8126F8F8B655EB6E1D949A49B2358262BDA986B4",
|
||||
"PreviousTxnLgrSeq": 29451256
|
||||
}
|
||||
},
|
||||
{
|
||||
"ModifiedNode": {
|
||||
"FinalFields": {
|
||||
"Flags": 0,
|
||||
"Owner": "rN7n7otQDd6FczFgLdSqtcsAUxDkw6fzRH",
|
||||
"RootIndex": "E590FC40B4F24D18341569BD3702A2D4E07E7BC04D11CE63608B67979E67030C"
|
||||
},
|
||||
"LedgerEntryType": "DirectoryNode",
|
||||
"LedgerIndex": "E590FC40B4F24D18341569BD3702A2D4E07E7BC04D11CE63608B67979E67030C"
|
||||
}
|
||||
}
|
||||
],
|
||||
"TransactionIndex": 7,
|
||||
"TransactionResult": "tesSUCCESS"
|
||||
},
|
||||
"status": "success",
|
||||
"validated": true
|
||||
}
|
||||
}
|
||||
</code></pre>
|
||||
<p>In the transaction's metadata, look for the following:</p>
|
||||
<ul>
|
||||
<li>A <code>DeletedNode</code> entry with <code>"LedgerEntryType": "PayChannel"</code>. The <code>LedgerIndex</code> field should match the Channel ID. This indicates that the channel was deleted.</li>
|
||||
<li>A <code>ModifiedNode</code> entry with <code>"LedgerEntryType": "AccountRoot"</code>. The change in the <code>Balance</code> field in <code>PreviousFields</code> and <code>FinalFields</code> reflects the unspent XRP being returned to the payer.</li>
|
||||
</ul>
|
||||
<p>Those fields indicate that the payment channel is closed.</p>
|
||||
<h2 id="conclusion">Conclusion</h2>
|
||||
<p>This concludes the tutorial of Payment Channel usage. Ripple encourages users to find unique and interesting use cases to take full advantage of the speed and convenience of payment channels.</p>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<footer class="content-info" role="contentinfo">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-sm-12 absolute_bottom_footer">
|
||||
<div class="col-sm-8">
|
||||
<span>© 2013 - 2017 Ripple Labs, Inc. All Rights Reserved.</span>
|
||||
<span><a href="/terms-of-use/">Terms</a></span>
|
||||
<span><a href="/privacy-policy/">Privacy</a></span>
|
||||
</div>
|
||||
</div><!-- /.absolute_bottom_footer -->
|
||||
|
||||
</div><!-- /.row -->
|
||||
</div><!-- /.container -->
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,582 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<meta name="viewport" content="width=device-width">
|
||||
|
||||
<title>Reliable Transaction Submission - Ripple Developer Portal</title>
|
||||
|
||||
<!-- favicon -->
|
||||
<link rel="icon" href="favicon.ico" type="image/x-icon">
|
||||
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon">
|
||||
|
||||
<!-- jQuery -->
|
||||
<script src="assets/vendor/jquery-1.11.1.min.js"></script>
|
||||
|
||||
<!-- Custom Stylesheets. ripple.css includes bootstrap, font stuff -->
|
||||
<link href="assets/css/ripple.css" rel="stylesheet" />
|
||||
<link href="assets/css/devportal.css" rel="stylesheet" />
|
||||
|
||||
<!-- Bootstrap JS -->
|
||||
<script src="assets/vendor/bootstrap.min.js"></script>
|
||||
|
||||
|
||||
<!-- syntax highlighting -->
|
||||
<link rel="stylesheet" href="assets/vendor/docco.min.css" />
|
||||
<script src="assets/vendor/highlight.min.js"></script>
|
||||
|
||||
<!-- syntax selection js -->
|
||||
<script src="assets/js/multicodetab.js"></script>
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
$(".multicode").minitabs();
|
||||
hljs.initHighlighting();
|
||||
make_code_expandable();
|
||||
});
|
||||
</script>
|
||||
|
||||
<script src="assets/js/expandcode.js"></script>
|
||||
<script src="assets/js/fixsidebarscroll.js"></script>
|
||||
|
||||
<!-- fontawesome icons -->
|
||||
<link rel="stylesheet" href="assets/vendor/fontawesome/css/font-awesome.min.css" />
|
||||
|
||||
</head>
|
||||
|
||||
<body class="page page-template page-template-template-dev-portal page-template-template-dev-portal-php sidebar-primary wpb-js-composer js-comp-ver-3.6.2 vc_responsive">
|
||||
<header role="banner" class="banner navbar navbar-default navbar-fixed-top initial_header">
|
||||
<div class="container">
|
||||
<div class="navbar-header">
|
||||
<a href="index.html" class="navbar-brand"><img src="assets/img/ripple-logo-color.png" class="logo"></a>
|
||||
</div><!-- /.navbar-header -->
|
||||
<div class="nav">
|
||||
<div class="draft-warning">DRAFT PAGE</div>
|
||||
</div><!-- /.nav -->
|
||||
|
||||
</div><!-- /.container -->
|
||||
|
||||
<div class="subnav dev_nav">
|
||||
<div class="container">
|
||||
<ul id="menu-dev-menu" class="menu">
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">References <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="reference-rippleapi.html">RippleAPI</a></li>
|
||||
<li><a href="reference-rippled.html">rippled</a></li>
|
||||
<li><a href="reference-transaction-format.html">Transaction Format</a></li>
|
||||
<li><a href="reference-ledger-format.html">Ledger Format</a></li>
|
||||
<li><a href="reference-data-api.html">Ripple Data API v2</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorials <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="tutorial-multisign.html">How to Multi-Sign</a></li>
|
||||
<li><a href="tutorial-paychan.html">Payment Channels Tutorial</a></li>
|
||||
<li><a href="concept-issuing-and-operational-addresses.html">Issuing and Operational Addresses</a></li>
|
||||
<li><a href="tutorial-reliable-transaction-submission.html">Reliable Transaction Submission</a></li>
|
||||
<li><a href="tutorial-rippleapi-beginners-guide.html">RippleAPI Beginners Guide</a></li>
|
||||
<li><a href="tutorial-rippled-setup.html">rippled Setup</a></li>
|
||||
<li><a href="tutorial-gateway-guide.html">Gateway Guide</a></li>
|
||||
<li><a href="tutorial-listing-xrp.html">Listing XRP as an Exchange</a></li>
|
||||
<li><a href="tutorial-escrow.html">Escrow Tutorials</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Features <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="concept-accounts.html">Accounts</a></li>
|
||||
<li><a href="concept-amendments.html">Amendments</a></li>
|
||||
<li><a href="concept-consensus.html">Consensus Process</a></li>
|
||||
<li><a href="concept-reaching-consensus.html">Reaching Consensus in the XRP Ledger</a></li>
|
||||
<li><a href="concept-fee-voting.html">Fee Voting</a></li>
|
||||
<li><a href="concept-fees.html">Fees (Disambiguation)</a></li>
|
||||
<li><a href="concept-freeze.html">Freeze</a></li>
|
||||
<li><a href="concept-partial-payments.html">Partial Payments</a></li>
|
||||
<li><a href="concept-paths.html">Paths</a></li>
|
||||
<li><a href="concept-reserves.html">Reserves</a></li>
|
||||
<li><a href="concept-stand-alone-mode.html">Stand-Alone Mode</a></li>
|
||||
<li><a href="concept-transaction-cost.html">Transaction Cost</a></li>
|
||||
<li><a href="concept-transfer-fees.html">Transfer Fees</a></li>
|
||||
<li><a href="concept-noripple.html">Understanding the NoRipple flag</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Gateway Bulletins <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="gb-2015-06.html">GB-2015-06: Corrections to Autobridging</a></li>
|
||||
<li><a href="gb-2015-05.html">GB-2015-05: Historical Ledger Query Migration</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">API Tools <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="ripple-api-tool.html">WebSocket API Tool</a></li>
|
||||
<li><a href="data-api-v2-tool.html">Data API v2 Tool</a></li>
|
||||
<li><a href="tool-jsonrpc.html">rippled JSON-RPC Tool</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li><a href="https://github.com/ripple/ripple-dev-portal" title="GitHub">Site Source</a></li>
|
||||
</ul><!-- /#dev-menu -->
|
||||
</div><!-- /.subnav .container -->
|
||||
</div><!-- /.subnav -->
|
||||
</header>
|
||||
|
||||
|
||||
<div class="wrap container" role="document">
|
||||
<aside class="sidebar" role="complementary">
|
||||
<div class="dev_nav_wrapper">
|
||||
<div id="cont">
|
||||
<h5>In this category:</h5>
|
||||
<ul class="dev_nav_sidebar">
|
||||
<li class="level-1"><a href="index.html">Category: Tutorials</a></li>
|
||||
<li class="level-2"><a href="tutorial-multisign.html">How to Multi-Sign</a></li>
|
||||
<li class="level-2"><a href="tutorial-paychan.html">Payment Channels Tutorial</a></li>
|
||||
<li class="level-2"><a href="concept-issuing-and-operational-addresses.html">Issuing and Operational Addresses</a></li>
|
||||
<li class="level-2"><a href="tutorial-reliable-transaction-submission.html">Reliable Transaction Submission</a></li>
|
||||
<li class="level-2"><a href="tutorial-rippleapi-beginners-guide.html">RippleAPI Beginners Guide</a></li>
|
||||
<li class="level-2"><a href="tutorial-rippled-setup.html">rippled Setup</a></li>
|
||||
<li class="level-2"><a href="tutorial-gateway-guide.html">Gateway Guide</a></li>
|
||||
<li class="level-2"><a href="tutorial-listing-xrp.html">Listing XRP as an Exchange</a></li>
|
||||
<li class="level-2"><a href="tutorial-escrow.html">Escrow Tutorials</a></li>
|
||||
</ul>
|
||||
<hr />
|
||||
<h5>In this page:</h5>
|
||||
<ul class="dev_nav_sidebar" id="dactyl_toc_sidebar">
|
||||
<li class="level-1"><a href="#reliable-transaction-submission">Reliable Transaction Submission</a></li>
|
||||
<li class="level-2"><a href="#background">Background</a></li>
|
||||
<li class="level-3"><a href="#transaction-timeline">Transaction Timeline</a></li>
|
||||
<li class="level-3"><a href="#lastledgersequence">LastLedgerSequence</a></li>
|
||||
<li class="level-2"><a href="#best-practices">Best Practices</a></li>
|
||||
<li class="level-3"><a href="#reliable-transactions-submission">Reliable Transactions Submission</a></li>
|
||||
<li class="level-3"><a href="#submission">Submission</a></li>
|
||||
<li class="level-3"><a href="#verification">Verification</a></li>
|
||||
<li class="level-2"><a href="#technical-application">Technical Application</a></li>
|
||||
<li class="level-3"><a href="#rippled-submitting-and-verifying-transactions">rippled - Submitting and Verifying Transactions</a></li>
|
||||
<li class="level-2"><a href="#additional-resources">Additional Resources</a></li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
<main class="main" role="main">
|
||||
<div class='content'>
|
||||
<h1 id="reliable-transaction-submission">Reliable Transaction Submission</h1>
|
||||
<p>Financial institutions and other services using the XRP Ledger should use the best practices described here to make sure that transactions are validated or rejected in a verifiable and prompt way. You should submit transactions to trusted (locally operated) <code>rippled</code> servers.</p>
|
||||
<p>The best practices detailed in this document allow applications to submit transactions to the XRP Ledger while achieving:</p>
|
||||
<ol>
|
||||
<li><a href="https://en.wikipedia.org/wiki/Idempotence">Idempotency</a> - Transactions should be processed once and only once, or not at all.</li>
|
||||
<li>Verifiability - Applications can determine the final result of a transaction.</li>
|
||||
</ol>
|
||||
<p>Applications which fail to implement best practices are at risk of the following errors:</p>
|
||||
<ol>
|
||||
<li>Submitting transactions which are inadvertently never executed.</li>
|
||||
<li>Mistaking provisional transaction results for their final, immutable results.</li>
|
||||
<li>Failing to find authoritative results of transactions previously applied to the ledger.</li>
|
||||
</ol>
|
||||
<p>These types of errors can potentially lead to serious problems. For example, an application that fails to find a prior successful payment transaction might erroneously submit another transaction, duplicating the original payment. This underscores the importance that applications base their actions on authoritive transaction results, using the techniques described in this document.</p>
|
||||
<h2 id="background">Background</h2>
|
||||
<p>The XRP Ledger protocol provides a ledger shared across all servers in the network. Through a <a href="https://ripple.com/build/ripple-ledger-consensus-process/">process of consensus and validation</a>, the network agrees on order in which transactions are applied to (or omitted from) the ledger.</p>
|
||||
<p>Well-formed transactions submitted to trusted XRP Ledger servers are usually validated or rejected in a matter of seconds. There are cases, however, in which a well-formed transaction is neither validated nor rejected this quickly. One specific case can occur if the global <a href="concept-transaction-cost.html">transaction cost</a> increases after an application sends a transaction. If the transaction cost increases above what has been specified in the transaction, the transaction is not included in the next validated ledger. If at some later date the global transaction cost decreases, the transaction could be included in a later ledger. If the transaction does not specify an expiration, there is no limit to how much later this can occur.</p>
|
||||
<p>If a power or network outage occurs, applications face more challenges finding the status of submitted transactions. Applications must take care both to properly submit a transaction and later to properly get authoritative results.</p>
|
||||
<h3 id="transaction-timeline">Transaction Timeline</h3>
|
||||
<p>The XRP Ledger provides several APIs for submitting transactions, including <a href="reference-rippled.html"><code>rippled</code></a>, and <a href="reference-rippleapi.html">RippleAPI</a>. Regardless of the API used, the transaction is applied to the ledger as follows.</p>
|
||||
<ol>
|
||||
<li>An account owner creates and signs a transaction.</li>
|
||||
<li>The owner submits the transaction to the network as a candidate transaction.<ul>
|
||||
<li>Malformed or nonsensical transactions are rejected immediately.</li>
|
||||
<li>Well-formed transactions may provisionally succeed, then later fail.</li>
|
||||
<li>Well-formed transactions may provisionally fail, then later succeed.</li>
|
||||
<li>Well-formed transactions may provisionally succeed, and then later succeed in a slightly different way. (For example, by consuming a different offer and achieving a better or worse exchange rate than the provisional execution.)</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>Through consensus and validation, the transaction is applied to the ledger. Even some failed transactions are applied, to enforce a cost for being propagated through the network.</li>
|
||||
<li>The validated ledger includes the transaction, and its effects are reflected in the ledger state.<ul>
|
||||
<li>Transaction results are no longer provisional, success or failure is now final and immutable.</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ol>
|
||||
<p class="devportal-callout note"><strong>Note:</strong> When submitting a transaction via <code>rippled</code>, a successful status code returned from a submit command indicates the <code>rippled</code> server has received the candidate transaction. The transaction may or may not be applied to a validated ledger.</p>
|
||||
<p>APIs may return provisional results based on the result of applying candidate transactions to the current, in-progress ledger. Applications must not confuse these with the final, <em>immutable</em>, results of a transaction. Immutable results are found only in validated ledgers. Applications may need to query the status of a transaction repeatedly, until the ledger containing the transaction results is validated.</p>
|
||||
<p>While applying transactions, <code>rippled</code> servers use the <em>last validated ledger</em>, a snapshot of the ledger state based on transactions the entire network has validated. The process of consensus and validation apply a set of new transactions to the last validated ledger in canonical order, resulting in a new validated ledger. This new validated ledger instance and the ones that preceded it form the ledger history.</p>
|
||||
<p>Each validated ledger instance has a sequence number, which is one greater than the sequence number of the preceding instance. Each ledger also has an identifying hash value, which is uniquely determined from its contents. There may be many different versions of in-progress ledgers, which have the same sequence number but different hash values. Only one version can ever be validated.</p>
|
||||
<p>Each validated ledger has a canonical order in which transactions apply. This order is deterministic based on the final transaction set of the ledger. In contrast, each <code>rippled</code> server's in-progress ledger is calculated incrementally, as transactions are received. The order in which transactions execute provisionally is usually not the same as the order in which transactions execute to build a new validated ledger. This is one reason why the provisional outcome of a transaction may be different than the final result. For example, a payment may achieve a different final exchange rate depending on whether it executes before or after another payment that would consume the same offer.</p>
|
||||
<h3 id="lastledgersequence">LastLedgerSequence</h3>
|
||||
<p><a href="reference-transaction-format.html#lastledgersequence"><code>LastLedgerSequence</code></a> is an optional parameter of all transactions. This instructs the XRP Ledger that a transaction must be validated on or before a specific ledger instance. The XRP Ledger never includes a transaction in a ledger instance whose sequence number is higher than the transaction's <code>LastLedgerSequence</code> parameter.</p>
|
||||
<p>Use the <code>LastLedgerSequence</code> parameter to prevent undesirable cases where a transaction is not confirmed promptly but could be included in a future ledger. You should specify the <code>LastLedgerSequence</code> parameter on every transaction. Automated processes should use a value of 4 greater than the last validated ledger index to make sure that a transaction is validated or rejected in a predictable and prompt way.</p>
|
||||
<p>Applications using <code>rippled</code> APIs should explicitly specify a <code>LastLedgerSequence</code> when submitting transactions. RippleAPI uses the <code>maxLedgerVersion</code> field of <a href="reference-rippleapi.html#transaction-instructions">Transaction Instructions</a> to specify the <code>LastLedgerSequence</code>. RippleAPI automatically provides an appropriate value by default. You can specify <code>maxLedgerVersion</code> as <code>null</code> to intentionally omit <code>LastLedgerSequence</code>, in case you want a transaction that can be executed after an unlimited amount of time.</p>
|
||||
<h2 id="best-practices">Best Practices</h2>
|
||||
<h3 id="reliable-transactions-submission">Reliable Transactions Submission</h3>
|
||||
<p>Applications submitting transactions should use the following practices to submit reliably even in the event that a process dies or other failure occurs. Application transaction results must be verified so that applications can act on the final, validated results.</p>
|
||||
<p>Submission and verification are two separate procedures which may be implemented using the logic described in this document.</p>
|
||||
<ol>
|
||||
<li>Submission - The transaction is submitted to the network and a provisional result is returned.</li>
|
||||
<li>Verification - The authoritative result is determined by examining validated ledgers.</li>
|
||||
</ol>
|
||||
<h3 id="submission">Submission</h3>
|
||||
<p><a href="https://en.wikipedia.org/wiki/Persistence_%28computer_science%29">Persist</a> details of the transaction before submission, in case of power failure or network failure before submission completes. On restart, the persisted values make it possible to verify the status of the transaction.</p>
|
||||
<p>The submission process:</p>
|
||||
<ol>
|
||||
<li>Construct and sign the transaction<ul>
|
||||
<li>Include <code>LastLedgerSequence</code> parameter</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>Persist the transaction details, saving:<ul>
|
||||
<li>Transaction hash</li>
|
||||
<li><code>LastLedgerSequence</code></li>
|
||||
<li>Sender address and sequence number</li>
|
||||
<li>Application-specific data, as needed</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>Submit the transaction</li>
|
||||
</ol>
|
||||
<h3 id="verification">Verification</h3>
|
||||
<p>During normal operation, applications may check the status of submitted transactions by their hashes; or, depending on the API used, receive notifications when transactions have been validated (or failed). This normal operation may be interrupted, for example by network failures or power failures. In case of such interruption applications need to reliably verify the status of transactions which may or may not have been submitted to the network before the interruption.</p>
|
||||
<p>On restart, or the determination of a new last validated ledger (pseudocode):</p>
|
||||
<pre><code>For each persisted transaction without validated result:
|
||||
Query transaction by hash
|
||||
If (result appears in validated ledger)
|
||||
Persist the final result
|
||||
If (result code is tesSUCCESS)
|
||||
Application may act based on successful transaction
|
||||
Else
|
||||
Application may act based on failure
|
||||
Maybe resubmit with new LastLedgerSequence and Fee
|
||||
Else if (LastLedgerSequence > newest validated ledger)
|
||||
Wait for more ledgers to be validated
|
||||
Else
|
||||
If (server has contiguous ledger history up to and
|
||||
including the ledger identified by LastLedgerSequence)
|
||||
The transaction failed
|
||||
Submit a new transaction, if appropriate for application
|
||||
Else
|
||||
Repeat submission of original transaction
|
||||
</code></pre>
|
||||
<h2 id="technical-application">Technical Application</h2>
|
||||
<p>To implement the transaction submission and verification best practices, applications need to do the following:</p>
|
||||
<ol>
|
||||
<li>Determine the signing account's next sequence number<ul>
|
||||
<li>Each transaction has an account-specific sequence number. This guarantees the order in which transactions signed by an account are executed and makes it safe to resubmit a transaction without danger of the transaction being applied to the ledger more than once.</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>Decide on a <code>LastLedgerSequence</code><ul>
|
||||
<li>A transaction's <code>LastLedgerSequence</code> is calculated from the last validated ledger sequence number.</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>Construct and sign the transaction<ul>
|
||||
<li>Persist the details of a signed transaction before submission.</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>Submit the transaction<ul>
|
||||
<li>Initial results are provisional and subject to change.</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>Determine the final result of a transaction<ul>
|
||||
<li>Final results are an immutable part of the ledger history.</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ol>
|
||||
<p>How the application does these actions depends on the API the application uses. An application may use any of the following interfaces:</p>
|
||||
<ol>
|
||||
<li><a href="reference-rippled.html"><code>rippled</code>'s internal APIs</a></li>
|
||||
<li><a href="reference-rippleapi.html">RippleAPI</a></li>
|
||||
<li>Any number of other software APIs layered on top of <code>rippled</code></li>
|
||||
</ol>
|
||||
<h3 id="rippled-submitting-and-verifying-transactions">rippled - Submitting and Verifying Transactions</h3>
|
||||
<h4 id="determine-the-account-sequence">Determine the Account Sequence</h4>
|
||||
<p><code>rippled</code> provides the <a href="reference-rippled.html#account-info">account_info</a> method to learn an account's sequence number in the last validated ledger.</p>
|
||||
<p>JSON-RPC Request:</p>
|
||||
<pre><code>{
|
||||
"method": "account_info",
|
||||
"params": [
|
||||
{
|
||||
"account": "rG5Ro9e3uGEZVCh3zu5gB9ydKUskCs221W",
|
||||
"ledger": "validated"
|
||||
}
|
||||
]
|
||||
}
|
||||
</code></pre>
|
||||
<p>Response body:</p>
|
||||
<pre><code>{
|
||||
"result": {
|
||||
"validated": true,
|
||||
"status": "success",
|
||||
"ledger_index": 10266396,
|
||||
"account_data": {
|
||||
"index": "96AB97A1BBC37F4F8A22CE28109E0D39D709689BDF412FE8EDAFB57A55E37F38",
|
||||
"Sequence": 4,
|
||||
"PreviousTxnLgrSeq": 9905632,
|
||||
"PreviousTxnID": "CAEE0E34B3DB50A7A0CA486E3A236513531DE9E52EAC47CE4C26332CC847DE26",
|
||||
"OwnerCount": 2,
|
||||
"LedgerEntryType": "AccountRoot",
|
||||
"Flags": 0,
|
||||
"Balance": "49975988",
|
||||
"Account": "rG5Ro9e3uGEZVCh3zu5gB9ydKUskCs221W"
|
||||
}
|
||||
}
|
||||
}
|
||||
</code></pre>
|
||||
<p>In this example, the account's sequence is <strong>4</strong> (note <code>"Sequence": 4</code>, in <code>"account_data"</code>) as of the last validated ledger (note <code>"ledger": "validated"</code> in the request, and <code>"validated": "true"</code> in the response).</p>
|
||||
<p>If an application were to submit three transactions signed by this account, they would use sequence numbers 4, 5, and 6. To submit multiple transactions without waiting for validation of each, an application should keep a running account sequence number.</p>
|
||||
<h4 id="determine-the-last-validated-ledger">Determine the Last Validated Ledger</h4>
|
||||
<p><code>rippled</code> provides the <a href="reference-rippled.html#server-state">server_state</a> command which returns the ledger sequence number of the last validated ledger.</p>
|
||||
<p>Request:</p>
|
||||
<pre><code>{
|
||||
"id": "client id 1",
|
||||
"method": "server_state"
|
||||
}
|
||||
</code></pre>
|
||||
<p>Response:</p>
|
||||
<pre><code>{
|
||||
"result": {
|
||||
"status": "success",
|
||||
"state": {
|
||||
"validation_quorum": 3,
|
||||
"validated_ledger": {
|
||||
"seq": 10268596,
|
||||
"reserve_inc": 5000000,
|
||||
"reserve_base": 20000000,
|
||||
"hash": "0E0901DA980251B8A4CCA17AB4CA6C3168FE83FA1D3F781AFC5B9B097FD209EF",
|
||||
"close_time": 470798600,
|
||||
"base_fee": 10
|
||||
},
|
||||
"server_state": "full",
|
||||
"published_ledger": 10268596,
|
||||
"pubkey_node": "n9LGg37Ya2SS9TdJ4XEuictrJmHaicdgTKiPJYi8QRSdvQd3xMnK",
|
||||
"peers": 58,
|
||||
"load_factor": 256000,
|
||||
"load_base": 256,
|
||||
"last_close": {
|
||||
"proposers": 5,
|
||||
"converge_time": 3004
|
||||
},
|
||||
"io_latency_ms": 2,
|
||||
"fetch_pack": 10121,
|
||||
"complete_ledgers": "10256331-10256382,10256412-10268596",
|
||||
"build_version": "0.26.4-sp3-private"
|
||||
}
|
||||
}
|
||||
}
|
||||
</code></pre>
|
||||
<p>In this example the last validated ledger sequence number is 10268596 (found under <code>result.state.validated_ledger</code> in the response). Note also this example indicates a gap in ledger history. The server used here would not be able to provide information about the transactions applied during that gap (ledgers 10256383 through 10256411). If configured to do so, the server eventually retrieves that part of the ledger history.</p>
|
||||
<h4 id="construct-the-transaction">Construct the Transaction</h4>
|
||||
<p><code>rippled</code> provides the <a href="reference-rippled.html#sign">sign method</a> to prepare a transaction for submission. This method requires an account secret, which should only be passed to trusted <code>rippled</code> instances. This example issues 10 FOO (a made-up currency) to another XRP Ledger address.</p>
|
||||
<p>Request:</p>
|
||||
<pre><code>{
|
||||
"method": "sign",
|
||||
"params": [
|
||||
{
|
||||
"offline": true,
|
||||
"secret": "sssssssssssssssssssssssssssss",
|
||||
"tx_json": {
|
||||
"Account": "rG5Ro9e3uGEZVCh3zu5gB9ydKUskCs221W",
|
||||
"Sequence": 4,
|
||||
"LastLedgerSequence": 10268600,
|
||||
"Fee": 10000,
|
||||
"Amount": {
|
||||
"currency": "FOO",
|
||||
"issuer": "rG5Ro9e3uGEZVCh3zu5gB9ydKUskCs221W",
|
||||
"value": "10"
|
||||
},
|
||||
"Destination": "rawz2WQ8i9FdTHp4KSNpBdyxgFqNpKe8fM",
|
||||
"TransactionType": "Payment"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
</code></pre>
|
||||
<p>Notice the application specifies the account sequence <code>"Sequence": 4</code>, learned from an earlier call to <code>account_info</code>, to avoid <code>tefPAST_SEQ</code> errors.</p>
|
||||
<p>Notice also the <code>LastLedgerSequence</code> based on the last validated ledger our application learned from <code>server_state</code>. The recommendation for backend applications is to use <em>(last validated ledger sequence + 4)</em>. Alternately, use a value of <em>(current ledger + 3)</em>. If <code>LastLedgerSequence</code> is miscalculated and less than the last validated ledger, the transaction fails with <code>tefMAX_LEDGER</code> error.</p>
|
||||
<p>Response:</p>
|
||||
<pre><code>{
|
||||
"result": {
|
||||
"tx_json": {
|
||||
"hash": "395C313F6F11F70FEBAF3785529A6D6DE3F44C7AF679515A7EAE22B30146DE57",
|
||||
"TxnSignature": "304402202646962A21EC0516FCE62DC9280F79E7265778C571E9410D795E67BB72A2D8E402202FF4AF7B2E2160F5BCA93011CB548014626CAC7FCBEBDB81FE8193CEFF69C753",
|
||||
"TransactionType": "Payment",
|
||||
"SigningPubKey": "0267268EE0DDDEE6A862C9FF9DDAF898CF17060A673AF771B565AA2F4AE24E3FC5",
|
||||
"Sequence": 4,
|
||||
"LastLedgerSequence": 10268600,
|
||||
"Flags": 2147483648,
|
||||
"Fee": "10000",
|
||||
"Destination": "rawz2WQ8i9FdTHp4KSNpBdyxgFqNpKe8fM",
|
||||
"Amount": {
|
||||
"value": "10",
|
||||
"issuer": "rG5Ro9e3uGEZVCh3zu5gB9ydKUskCs221W",
|
||||
"currency": "FOO"
|
||||
},
|
||||
"Account": "rG5Ro9e3uGEZVCh3zu5gB9ydKUskCs221W"
|
||||
},
|
||||
"tx_blob": "12000022800000002400000004201B009CAFB861D4C38D7EA4C68000000000000000000000000000464F4F0000000000AC5FA3BB28A09BD2EC1AE0EED2315060E83D796A68400000000000271073210267268EE0DDDEE6A862C9FF9DDAF898CF17060A673AF771B565AA2F4AE24E3FC57446304402202646962A21EC0516FCE62DC9280F79E7265778C571E9410D795E67BB72A2D8E402202FF4AF7B2E2160F5BCA93011CB548014626CAC7FCBEBDB81FE8193CEFF69C7538114AC5FA3BB28A09BD2EC1AE0EED2315060E83D796A831438BC6F9F5A6F6C4E474DB0D59892E90C2C7CED5C",
|
||||
"status": "success"
|
||||
}
|
||||
}
|
||||
</code></pre>
|
||||
<p>Applications should persist the transaction's hash before submitting. The result of the <code>sign</code> method includes the hash under <code>tx_json</code>.</p>
|
||||
<h4 id="submit-the-transaction">Submit the transaction</h4>
|
||||
<p><code>rippled</code> provides the <a href="reference-rippled.html#submit"><code>submit</code> method</a>, allowing us to submit the signed transaction. This uses the <code>tx_blob</code> parameter that was returned by the <code>sign</code> method.</p>
|
||||
<p>Request:</p>
|
||||
<pre><code>{
|
||||
"method": "submit",
|
||||
"params": [
|
||||
{
|
||||
"tx_blob": "12000022800000002400000004201B009CAFB861D4C38D7EA4C68000000000000000000000000000464F4F0000000000AC5FA3BB28A09BD2EC1AE0EED2315060E83D796A68400000000000271073210267268EE0DDDEE6A862C9FF9DDAF898CF17060A673AF771B565AA2F4AE24E3FC57446304402202646962A21EC0516FCE62DC9280F79E7265778C571E9410D795E67BB72A2D8E402202FF4AF7B2E2160F5BCA93011CB548014626CAC7FCBEBDB81FE8193CEFF69C7538114AC5FA3BB28A09BD2EC1AE0EED2315060E83D796A831438BC6F9F5A6F6C4E474DB0D59892E90C2C7CED5C"
|
||||
}
|
||||
]
|
||||
}
|
||||
</code></pre>
|
||||
<p>Response:</p>
|
||||
<pre><code>{
|
||||
"result": {
|
||||
"tx_json": {
|
||||
"hash": "395C313F6F11F70FEBAF3785529A6D6DE3F44C7AF679515A7EAE22B30146DE57",
|
||||
"TxnSignature": "304402202646962A21EC0516FCE62DC9280F79E7265778C571E9410D795E67BB72A2D8E402202FF4AF7B2E2160F5BCA93011CB548014626CAC7FCBEBDB81FE8193CEFF69C753",
|
||||
"TransactionType": "Payment",
|
||||
"SigningPubKey": "0267268EE0DDDEE6A862C9FF9DDAF898CF17060A673AF771B565AA2F4AE24E3FC5",
|
||||
"Sequence": 4,
|
||||
"LastLedgerSequence": 10268600,
|
||||
"Flags": 2147483648,
|
||||
"Fee": "10000",
|
||||
"Destination": "rawz2WQ8i9FdTHp4KSNpBdyxgFqNpKe8fM",
|
||||
"Amount": {
|
||||
"value": "10",
|
||||
"issuer": "rG5Ro9e3uGEZVCh3zu5gB9ydKUskCs221W",
|
||||
"currency": "FOO"
|
||||
},
|
||||
"Account": "rG5Ro9e3uGEZVCh3zu5gB9ydKUskCs221W"
|
||||
},
|
||||
"tx_blob": "12000022800000002400000004201B009CAFB861D4C38D7EA4C68000000000000000000000000000464F4F0000000000AC5FA3BB28A09BD2EC1AE0EED2315060E83D796A68400000000000271073210267268EE0DDDEE6A862C9FF9DDAF898CF17060A673AF771B565AA2F4AE24E3FC57446304402202646962A21EC0516FCE62DC9280F79E7265778C571E9410D795E67BB72A2D8E402202FF4AF7B2E2160F5BCA93011CB548014626CAC7FCBEBDB81FE8193CEFF69C7538114AC5FA3BB28A09BD2EC1AE0EED2315060E83D796A831438BC6F9F5A6F6C4E474DB0D59892E90C2C7CED5C",
|
||||
"status": "success",
|
||||
"engine_result_message": "The transaction was applied.",
|
||||
"engine_result_code": 0,
|
||||
"engine_result": "tesSUCCESS"
|
||||
}
|
||||
}
|
||||
</code></pre>
|
||||
<p>This a <strong>preliminary</strong> result. Final results are only available from validated ledgers. The lack of a <code>"validated": true</code> field indicates that this is <strong>not an immutable result</strong>.</p>
|
||||
<h4 id="verify-the-transaction">Verify the Transaction</h4>
|
||||
<p>The transaction hash, generated when the transaction was signed, is passed to the <a href="reference-rippled.html#tx"><code>tx</code> method</a> to retrieve the result of a transaction.</p>
|
||||
<p>Request:</p>
|
||||
<pre><code>{
|
||||
"method": "tx",
|
||||
"params": [
|
||||
{
|
||||
"transaction": "395C313F6F11F70FEBAF3785529A6D6DE3F44C7AF679515A7EAE22B30146DE57",
|
||||
"binary": false
|
||||
}
|
||||
]
|
||||
}
|
||||
</code></pre>
|
||||
<p>Response:</p>
|
||||
<pre><code>{
|
||||
"result": {
|
||||
"validated": true,
|
||||
"status": "success",
|
||||
"meta": {
|
||||
"TransactionResult": "tesSUCCESS",
|
||||
"TransactionIndex": 2,
|
||||
"AffectedNodes": [...]
|
||||
},
|
||||
"ledger_index": 10268599[d],
|
||||
"inLedger": 10268599,
|
||||
"hash": "395C313F6F11F70FEBAF3785529A6D6DE3F44C7AF679515A7EAE22B30146DE57",
|
||||
"date": 470798270,
|
||||
"TxnSignature": "304402202646962A21EC0516FCE62DC9280F79E7265778C571E9410D795E67BB72A2D8E402202FF4AF7B2E2160F5BCA93011CB548014626CAC7FCBEBDB81FE8193CEFF69C753",
|
||||
"TransactionType": "Payment",
|
||||
"SigningPubKey": "0267268EE0DDDEE6A862C9FF9DDAF898CF17060A673AF771B565AA2F4AE24E3FC5",
|
||||
"Sequence": 4,
|
||||
"LastLedgerSequence": 10268600,
|
||||
"Flags": 2147483648,
|
||||
"Fee": "10000",
|
||||
"Destination": "rawz2WQ8i9FdTHp4KSNpBdyxgFqNpKe8fM",
|
||||
"Amount": {
|
||||
"value": "10",
|
||||
"issuer": "rG5Ro9e3uGEZVCh3zu5gB9ydKUskCs221W",
|
||||
"currency": "FOO"
|
||||
},
|
||||
"Account": "rG5Ro9e3uGEZVCh3zu5gB9ydKUskCs221W"
|
||||
}
|
||||
}
|
||||
</code></pre>
|
||||
<p>This example response shows <code>"validated": true</code>, indicating the transaction has been included in a validated ledger, so the result of the transaction is immutable. Further, the metadata includes <code>"TransactionResult": "tesSUCCESS"</code>, indicating the transaction was applied to the ledger.</p>
|
||||
<p>If the response does not include <code>"validated": true</code>, the result is provisional and subject to change. To retrieve a final result, applications must invoke the <code>tx</code> method again, allowing enough time for the network to validate more ledger instances. It may be necessary to wait for the ledger specified in <code>LastLedgerSequence</code> to be validated, although if the transaction is included in an earlier validated ledger the result become immutable at that time.</p>
|
||||
<h4 id="verify-missing-transaction">Verify Missing Transaction</h4>
|
||||
<p>Applications must handle cases where a call to the <a href="reference-rippled.html#tx"><code>tx</code> method</a> returns a <code>txnNotFound</code> error.</p>
|
||||
<pre><code>{
|
||||
"result": {
|
||||
"status": "error",
|
||||
"request": {
|
||||
"transaction": "395C313F6F11F70FEBAF3785529A6D6DE3F44C7AF679515A7EAE22B30146DE56",
|
||||
"command": "tx",
|
||||
"binary": false
|
||||
},
|
||||
"error_message": "Transaction not found.",
|
||||
"error_code": 24,
|
||||
"error": "txnNotFound"
|
||||
}
|
||||
}
|
||||
</code></pre>
|
||||
<p>The <code>txnNotFound</code> result code occurs in cases where the transaction is not included in any ledger. However, it could also occur when a <code>rippled</code> instance does not have a complete ledger history, or if the transaction has not yet propagated to the <code>rippled</code> instance. Applications should make further queries to determine how to react.</p>
|
||||
<p>The <a href="reference-rippled.html#server-state"><code>server_state</code> method</a> (used earlier to determine the last validated ledger) indicates how complete the ledger history is, under <code>result.state.complete_ledgers</code>.</p>
|
||||
<pre><code>{
|
||||
"result": {
|
||||
"status": "success",
|
||||
"state": {
|
||||
"validation_quorum": 3,
|
||||
"validated_ledger": {
|
||||
"seq": 10269447,
|
||||
"reserve_inc": 5000000,
|
||||
"reserve_base": 20000000,
|
||||
"hash": "D05C7ECC66DD6F4FEA3A6394F209EB5D6824A76C16438F562A1749CCCE7EAFC2",
|
||||
"close_time": 470802340,
|
||||
"base_fee": 10
|
||||
},
|
||||
"server_state": "full",
|
||||
"pubkey_node": "n9LJ5eCNjeUXQpNXHCcLv9PQ8LMFYy4W8R1BdVNcpjc1oDwe6XZF",
|
||||
"peers": 84,
|
||||
"load_factor": 256000,
|
||||
"load_base": 256,
|
||||
"last_close": {
|
||||
"proposers": 5,
|
||||
"converge_time": 2002
|
||||
},
|
||||
"io_latency_ms": 1,
|
||||
"complete_ledgers": "10256331-10256382,10256412-10269447",
|
||||
"build_version": "0.26.4-sp3-private"
|
||||
}
|
||||
}
|
||||
}
|
||||
</code></pre>
|
||||
<p>Our example transaction specified <code>LastLedgerSequence</code> 10268600, based on the last validated ledger at the time, plus four. To determine whether our missing transaction has permanently failed, our <code>rippled</code> server must have ledgers 10268597 through 10268600. If the server has those validated ledgers in its history, <strong>and</strong> <code>tx</code> returns <code>txnNotFound</code>, then the transaction has failed and cannot be included in any future ledger. In this case, application logic may dictate building and submitting a replacement transaction with the same account sequence and updated <code>LastLedgerSequence</code>.</p>
|
||||
<p>The server may report a last validated ledger sequence number less than the specified <code>LastLedgerSequence</code>. If so, the <code>txnNotFound</code> indicates either (a) the submitted transaction has not been distributed to the network, or (b) the transaction has been distributed to the network but has not yet been processed. To handle the former case, applications may submit again the same signed transaction. Because the transaction has a unique account sequence number, it can be processed at most once.</p>
|
||||
<p>Finally the server may show one or more gaps in the transaction history. The <code>completed_ledgers</code> field shown in the response above indicates that ledgers 10256383 through 10256411 are missing from this rippled instance. Our example transaction can only appear in ledgers 10268597 - 10268600 (based on when it was submitted and <code>LastLedgerSequence</code>), so the gap shown here is not relevant. However, if the gap indicated a ledger in that range was missing, then an application would need to query another rippled server (or wait for this one to retrieve the missing ledgers) to determine that a <code>txnNotFound</code> result is immutable.</p>
|
||||
<h2 id="additional-resources">Additional Resources</h2>
|
||||
<ul>
|
||||
<li><a href="reference-transaction-format.html">Transaction Format</a></li>
|
||||
<li><a href="concept-transaction-cost.html">Transaction Cost</a></li>
|
||||
<li><a href="reference-transaction-format.html#lastledgersequence"><code>LastLedgerSequence</code> field</a></li>
|
||||
<li><a href="concept-consensus.html">Overview of XRP Ledger Consensus Process</a></li>
|
||||
<li><a href="concept-reaching-consensus.html">Reaching Consensus in the XRP Ledger</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<footer class="content-info" role="contentinfo">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-sm-12 absolute_bottom_footer">
|
||||
<div class="col-sm-8">
|
||||
<span>© 2013 - 2017 Ripple Labs, Inc. All Rights Reserved.</span>
|
||||
<span><a href="/terms-of-use/">Terms</a></span>
|
||||
<span><a href="/privacy-policy/">Privacy</a></span>
|
||||
</div>
|
||||
</div><!-- /.absolute_bottom_footer -->
|
||||
|
||||
</div><!-- /.row -->
|
||||
</div><!-- /.container -->
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,526 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<meta name="viewport" content="width=device-width">
|
||||
|
||||
<title>RippleAPI Beginners Guide - Ripple Developer Portal</title>
|
||||
|
||||
<!-- favicon -->
|
||||
<link rel="icon" href="favicon.ico" type="image/x-icon">
|
||||
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon">
|
||||
|
||||
<!-- jQuery -->
|
||||
<script src="assets/vendor/jquery-1.11.1.min.js"></script>
|
||||
|
||||
<!-- Custom Stylesheets. ripple.css includes bootstrap, font stuff -->
|
||||
<link href="assets/css/ripple.css" rel="stylesheet" />
|
||||
<link href="assets/css/devportal.css" rel="stylesheet" />
|
||||
|
||||
<!-- Bootstrap JS -->
|
||||
<script src="assets/vendor/bootstrap.min.js"></script>
|
||||
|
||||
|
||||
<!-- syntax highlighting -->
|
||||
<link rel="stylesheet" href="assets/vendor/docco.min.css" />
|
||||
<script src="assets/vendor/highlight.min.js"></script>
|
||||
|
||||
<!-- syntax selection js -->
|
||||
<script src="assets/js/multicodetab.js"></script>
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
$(".multicode").minitabs();
|
||||
hljs.initHighlighting();
|
||||
make_code_expandable();
|
||||
});
|
||||
</script>
|
||||
|
||||
<script src="assets/js/expandcode.js"></script>
|
||||
<script src="assets/js/fixsidebarscroll.js"></script>
|
||||
|
||||
<!-- fontawesome icons -->
|
||||
<link rel="stylesheet" href="assets/vendor/fontawesome/css/font-awesome.min.css" />
|
||||
|
||||
</head>
|
||||
|
||||
<body class="page page-template page-template-template-dev-portal page-template-template-dev-portal-php sidebar-primary wpb-js-composer js-comp-ver-3.6.2 vc_responsive">
|
||||
<header role="banner" class="banner navbar navbar-default navbar-fixed-top initial_header">
|
||||
<div class="container">
|
||||
<div class="navbar-header">
|
||||
<a href="index.html" class="navbar-brand"><img src="assets/img/ripple-logo-color.png" class="logo"></a>
|
||||
</div><!-- /.navbar-header -->
|
||||
<div class="nav">
|
||||
<div class="draft-warning">DRAFT PAGE</div>
|
||||
</div><!-- /.nav -->
|
||||
|
||||
</div><!-- /.container -->
|
||||
|
||||
<div class="subnav dev_nav">
|
||||
<div class="container">
|
||||
<ul id="menu-dev-menu" class="menu">
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">References <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="reference-rippleapi.html">RippleAPI</a></li>
|
||||
<li><a href="reference-rippled.html">rippled</a></li>
|
||||
<li><a href="reference-transaction-format.html">Transaction Format</a></li>
|
||||
<li><a href="reference-ledger-format.html">Ledger Format</a></li>
|
||||
<li><a href="reference-data-api.html">Ripple Data API v2</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorials <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="tutorial-multisign.html">How to Multi-Sign</a></li>
|
||||
<li><a href="tutorial-paychan.html">Payment Channels Tutorial</a></li>
|
||||
<li><a href="concept-issuing-and-operational-addresses.html">Issuing and Operational Addresses</a></li>
|
||||
<li><a href="tutorial-reliable-transaction-submission.html">Reliable Transaction Submission</a></li>
|
||||
<li><a href="tutorial-rippleapi-beginners-guide.html">RippleAPI Beginners Guide</a></li>
|
||||
<li><a href="tutorial-rippled-setup.html">rippled Setup</a></li>
|
||||
<li><a href="tutorial-gateway-guide.html">Gateway Guide</a></li>
|
||||
<li><a href="tutorial-listing-xrp.html">Listing XRP as an Exchange</a></li>
|
||||
<li><a href="tutorial-escrow.html">Escrow Tutorials</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Features <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="concept-accounts.html">Accounts</a></li>
|
||||
<li><a href="concept-amendments.html">Amendments</a></li>
|
||||
<li><a href="concept-consensus.html">Consensus Process</a></li>
|
||||
<li><a href="concept-reaching-consensus.html">Reaching Consensus in the XRP Ledger</a></li>
|
||||
<li><a href="concept-fee-voting.html">Fee Voting</a></li>
|
||||
<li><a href="concept-fees.html">Fees (Disambiguation)</a></li>
|
||||
<li><a href="concept-freeze.html">Freeze</a></li>
|
||||
<li><a href="concept-partial-payments.html">Partial Payments</a></li>
|
||||
<li><a href="concept-paths.html">Paths</a></li>
|
||||
<li><a href="concept-reserves.html">Reserves</a></li>
|
||||
<li><a href="concept-stand-alone-mode.html">Stand-Alone Mode</a></li>
|
||||
<li><a href="concept-transaction-cost.html">Transaction Cost</a></li>
|
||||
<li><a href="concept-transfer-fees.html">Transfer Fees</a></li>
|
||||
<li><a href="concept-noripple.html">Understanding the NoRipple flag</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Gateway Bulletins <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="gb-2015-06.html">GB-2015-06: Corrections to Autobridging</a></li>
|
||||
<li><a href="gb-2015-05.html">GB-2015-05: Historical Ledger Query Migration</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">API Tools <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="ripple-api-tool.html">WebSocket API Tool</a></li>
|
||||
<li><a href="data-api-v2-tool.html">Data API v2 Tool</a></li>
|
||||
<li><a href="tool-jsonrpc.html">rippled JSON-RPC Tool</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li><a href="https://github.com/ripple/ripple-dev-portal" title="GitHub">Site Source</a></li>
|
||||
</ul><!-- /#dev-menu -->
|
||||
</div><!-- /.subnav .container -->
|
||||
</div><!-- /.subnav -->
|
||||
</header>
|
||||
|
||||
|
||||
<div class="wrap container" role="document">
|
||||
<aside class="sidebar" role="complementary">
|
||||
<div class="dev_nav_wrapper">
|
||||
<div id="cont">
|
||||
<h5>In this category:</h5>
|
||||
<ul class="dev_nav_sidebar">
|
||||
<li class="level-1"><a href="index.html">Category: Tutorials</a></li>
|
||||
<li class="level-2"><a href="tutorial-multisign.html">How to Multi-Sign</a></li>
|
||||
<li class="level-2"><a href="tutorial-paychan.html">Payment Channels Tutorial</a></li>
|
||||
<li class="level-2"><a href="concept-issuing-and-operational-addresses.html">Issuing and Operational Addresses</a></li>
|
||||
<li class="level-2"><a href="tutorial-reliable-transaction-submission.html">Reliable Transaction Submission</a></li>
|
||||
<li class="level-2"><a href="tutorial-rippleapi-beginners-guide.html">RippleAPI Beginners Guide</a></li>
|
||||
<li class="level-2"><a href="tutorial-rippled-setup.html">rippled Setup</a></li>
|
||||
<li class="level-2"><a href="tutorial-gateway-guide.html">Gateway Guide</a></li>
|
||||
<li class="level-2"><a href="tutorial-listing-xrp.html">Listing XRP as an Exchange</a></li>
|
||||
<li class="level-2"><a href="tutorial-escrow.html">Escrow Tutorials</a></li>
|
||||
</ul>
|
||||
<hr />
|
||||
<h5>In this page:</h5>
|
||||
<ul class="dev_nav_sidebar" id="dactyl_toc_sidebar">
|
||||
<li class="level-1"><a href="#rippleapi-beginners-guide">RippleAPI Beginners Guide</a></li>
|
||||
<li class="level-1"><a href="#environment-setup">Environment Setup</a></li>
|
||||
<li class="level-2"><a href="#install-nodejs-and-npm">Install Node.js and npm</a></li>
|
||||
<li class="level-2"><a href="#use-npm-to-install-rippleapi-and-dependencies">Use NPM to install RippleAPI and dependencies</a></li>
|
||||
<li class="level-1"><a href="#first-rippleapi-script">First RippleAPI Script</a></li>
|
||||
<li class="level-2"><a href="#running-the-script">Running the script</a></li>
|
||||
<li class="level-2"><a href="#understanding-the-script">Understanding the script</a></li>
|
||||
<li class="level-3"><a href="#script-opening">Script opening</a></li>
|
||||
<li class="level-3"><a href="#instantiating-the-api">Instantiating the API</a></li>
|
||||
<li class="level-3"><a href="#connecting-and-promises">Connecting and Promises</a></li>
|
||||
<li class="level-3"><a href="#custom-code">Custom code</a></li>
|
||||
<li class="level-3"><a href="#cleanup">Cleanup</a></li>
|
||||
<li class="level-1"><a href="#waiting-for-validation">Waiting for Validation</a></li>
|
||||
<li class="level-1"><a href="#rippleapi-in-web-browsers">RippleAPI in Web Browsers</a></li>
|
||||
<li class="level-2"><a href="#build-instructions">Build Instructions</a></li>
|
||||
<li class="level-2"><a href="#example-browser-usage">Example Browser Usage</a></li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
<main class="main" role="main">
|
||||
<div class='content'>
|
||||
<h1 id="rippleapi-beginners-guide">RippleAPI Beginners Guide</h1>
|
||||
<p>This tutorial guides you through the basics of building an XRP Ledger-connected application using <a href="http://nodejs.org/">Node.js</a> and <a href="reference-rippleapi.html">RippleAPI</a>, a JavaScript API for accessing the XRP Ledger.</p>
|
||||
<p>The scripts and configuration files used in this guide are <a href="https://github.com/ripple/ripple-dev-portal/tree/master/content/code_samples/rippleapi_quickstart">available in the Ripple Dev Portal GitHub Repository</a>.</p>
|
||||
<h1 id="environment-setup">Environment Setup</h1>
|
||||
<p>The first step to using RippleAPI is setting up your development environment.</p>
|
||||
<h2 id="install-nodejs-and-npm">Install Node.js and npm</h2>
|
||||
<p>RippleAPI is built as an application for the Node.js runtime environment, so the first step is getting Node.js installed. RippleAPI requires Node.js version 0.12, version 4.x, or higher.</p>
|
||||
<p>This step depends on your operating system. We recommend <a href="https://nodejs.org/en/download/package-manager/">the official instructions for installing Node.js using a package manager</a> for your operating system. If the packages for Node.js and <code>npm</code> (Node Package Manager) are separate, install both. (This applies to Arch Linux, CentOS, Fedora, and RHEL.)</p>
|
||||
<p>After you have installed Node.js, you can check the version of the <code>node</code> binary from a command line:</p>
|
||||
<pre><code>node --version
|
||||
</code></pre>
|
||||
<p>On some platforms, the binary is named <code>nodejs</code> instead:</p>
|
||||
<pre><code>nodejs --version
|
||||
</code></pre>
|
||||
<h2 id="use-npm-to-install-rippleapi-and-dependencies">Use NPM to install RippleAPI and dependencies</h2>
|
||||
<p>RippleAPI uses the newest version of JavaScript, ECMAScript 6 (also known as ES2015). To use the new features of ECMAScript 6, RippleAPI depends on <a href="https://babeljs.io">Babel-Node</a> and its ES2015 presets. You can use <code>npm</code> to install RippleAPI and these dependencies together.</p>
|
||||
<h4 id="1-create-a-new-directory-for-your-project">1. Create a new directory for your project</h4>
|
||||
<p>Create a folder called (for example) <code>my_ripple_experiment</code>:</p>
|
||||
<pre><code>mkdir my_ripple_experiment && cd my_ripple_experiment
|
||||
</code></pre>
|
||||
<p>Optionally, start a <a href="https://git-scm.com/book/en/v2/Getting-Started-Installing-Git">Git</a> repository in that directory so you can track changes to your code.</p>
|
||||
<pre><code>git init
|
||||
</code></pre>
|
||||
<p>Alternatively, you can <a href="https://help.github.com/articles/create-a-repo/">create a repo on GitHub</a> to version and share your work. After setting it up, <a href="https://help.github.com/articles/cloning-a-repository/">clone the repo</a> to your local machine and <code>cd</code> into that directory.</p>
|
||||
<h4 id="2-create-a-new-packagejson-file-for-your-project">2. Create a new <code>package.json</code> file for your project.</h4>
|
||||
<p>Use the following template, which includes:</p>
|
||||
<ul>
|
||||
<li>RippleAPI itself (<code>ripple-lib</code>)</li>
|
||||
<li>Babel (<code>babel-cli</code>)</li>
|
||||
<li>The ECMAScript 6 presets for Babel (<code>babel-preset-es2015</code>)</li>
|
||||
<li>(Optional) <a href="http://eslint.org/">ESLint</a> (<code>eslint</code>) for checking code quality.</li>
|
||||
</ul>
|
||||
<pre><code>{
|
||||
"name": "my_ripple_experiment",
|
||||
"version": "0.0.1",
|
||||
"license": "MIT",
|
||||
"private": true,
|
||||
"//": "Change the license to something appropriate. You may want to use 'UNLICENSED' if you are just starting out.",
|
||||
"dependencies": {
|
||||
"ripple-lib": "*",
|
||||
"babel-cli": "^6.0.0",
|
||||
"babel-preset-es2015": "*"
|
||||
},
|
||||
"babel": {
|
||||
"presets": ["es2015"]
|
||||
},
|
||||
"devDependencies": {
|
||||
"eslint": "*"
|
||||
}
|
||||
}
|
||||
</code></pre>
|
||||
<h4 id="3-use-npm-to-install-the-dependencies">3. Use NPM to install the dependencies.</h4>
|
||||
<pre><code>npm install
|
||||
</code></pre>
|
||||
<p>This automatically installs all the dependencies defined in the <code>package.json</code> into the local folder <code>node_modules/</code>. (We recommend <em>not</em> using <code>npm -g</code> to install the dependencies globally.)</p>
|
||||
<p>The install process may take a while and end with a few warnings. You may safely ignore the following warnings:</p>
|
||||
<pre><code>npm WARN optional Skipping failed optional dependency /chokidar/fsevents:
|
||||
npm WARN notsup Not compatible with your operating system or architecture: fsevents@1.0.6
|
||||
npm WARN ajv@1.4.10 requires a peer of ajv-i18n@0.1.x but none was installed.
|
||||
</code></pre>
|
||||
<h1 id="first-rippleapi-script">First RippleAPI Script</h1>
|
||||
<p>This script, <code>get-account-info.js</code>, fetches information about a hard-coded account. Use it to test that RippleAPI works:</p>
|
||||
<pre><code>'use strict';
|
||||
const RippleAPI = require('ripple-lib').RippleAPI;
|
||||
|
||||
const api = new RippleAPI({
|
||||
server: 'wss://s1.ripple.com' // Public rippled server
|
||||
});
|
||||
api.connect().then(() => {
|
||||
/* begin custom code ------------------------------------ */
|
||||
const myAddress = 'rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn';
|
||||
|
||||
console.log('getting account info for', myAddress);
|
||||
return api.getAccountInfo(myAddress);
|
||||
|
||||
}).then(info => {
|
||||
console.log(info);
|
||||
console.log('getAccountInfo done');
|
||||
|
||||
/* end custom code -------------------------------------- */
|
||||
}).then(() => {
|
||||
return api.disconnect();
|
||||
}).then(() => {
|
||||
console.log('done and disconnected.');
|
||||
}).catch(console.error);
|
||||
</code></pre>
|
||||
<h2 id="running-the-script">Running the script</h2>
|
||||
<p>RippleAPI and the script both use the ECMAScript 6 version of JavaScript. That's why we installed Babel earlier. The easiest way to run ECMAScript 6 is to use the <code>babel-node</code> binary, which NPM installs in the <code>node_modules/.bin/</code> directory of your project. Thus, running the script looks like this:</p>
|
||||
<pre><code>./node_modules/.bin/babel-node get-account-info.js
|
||||
</code></pre>
|
||||
<p>Output:</p>
|
||||
<pre><code>getting account info for rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn
|
||||
{ sequence: 359,
|
||||
xrpBalance: '75.181663',
|
||||
ownerCount: 4,
|
||||
previousInitiatedTransactionID: 'E5C6DD25B2DCF534056D98A2EFE3B7CFAE4EBC624854DE3FA436F733A56D8BD9',
|
||||
previousAffectingTransactionID: 'E5C6DD25B2DCF534056D98A2EFE3B7CFAE4EBC624854DE3FA436F733A56D8BD9',
|
||||
previousAffectingTransactionLedgerVersion: 18489336 }
|
||||
getAccountInfo done
|
||||
done and disconnected.
|
||||
</code></pre>
|
||||
<h2 id="understanding-the-script">Understanding the script</h2>
|
||||
<p>In addition to RippleAPI-specific code, this script uses syntax and conventions that are recent developments in JavaScript. Let's divide the sample code into smaller chunks to explain each one.</p>
|
||||
<h3 id="script-opening">Script opening</h3>
|
||||
<pre><code>'use strict';
|
||||
const RippleAPI = require('ripple-lib').RippleAPI;
|
||||
</code></pre>
|
||||
<p>The opening line enables <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode">strict mode</a>. This is purely optional, but it helps you avoid some common pitfalls of JavaScript. See also: <a href="https://msdn.microsoft.com/library/br230269%28v=vs.94%29.aspx#Anchor_1">Restrictions on Code in Strict Mode</a>.</p>
|
||||
<p>The second line imports RippleAPI into the current scope using Node.js's require function. RippleAPI is one of <a href="https://github.com/ripple/ripple-lib/blob/develop/src/index.js">the modules <code>ripple-lib</code> exports</a>.</p>
|
||||
<h3 id="instantiating-the-api">Instantiating the API</h3>
|
||||
<pre><code>const api = new RippleAPI({
|
||||
server: 'wss://s1.ripple.com' // Public rippled server
|
||||
});
|
||||
</code></pre>
|
||||
<p>This section creates a new instance of the RippleAPI class, assigning it to the variable <code>api</code>. (The <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const"><code>const</code> keyword</a> means you can't reassign the value <code>api</code> to some other value. The internal state of the object can still change, though.)</p>
|
||||
<p>The one argument to the constructor is an options object, which has <a href="reference-rippleapi.html#parameters">a variety of options</a>. The <code>server</code> parameter tells it where it should connect to a <code>rippled</code> server.</p>
|
||||
<ul>
|
||||
<li>The example <code>server</code> setting uses a secure WebSocket connection to connect to one of the public servers that Ripple (the company) operates.</li>
|
||||
<li>If you don't include the <code>server</code> option, RippleAPI runs in <a href="reference-rippleapi.html#offline-functionality">offline mode</a> instead, which only provides methods that don't need network connectivity.</li>
|
||||
<li>You can specify a <a href="https://ripple.com/build/ripple-test-net/">Ripple Test Net</a> server instead to connect to the parallel-world Test Network instead of the production XRP Ledger.</li>
|
||||
<li>If you <a href="tutorial-rippled-setup.html">run your own <code>rippled</code></a>, you can instruct it to connect to your local server. For example, you might say <code>server: 'ws://localhost:5005'</code> instead.</li>
|
||||
</ul>
|
||||
<h3 id="connecting-and-promises">Connecting and Promises</h3>
|
||||
<pre><code>api.connect().then(() => {
|
||||
</code></pre>
|
||||
<p>The <a href="reference-rippleapi.html#connect">connect() method</a> is one of many RippleAPI methods that returns a <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise">Promise</a>, which is a special kind of JavaScript object. A Promise is designed to do an asynchronous operation that returns a value later, such as querying the XRP Ledger.</p>
|
||||
<p>When you get a Promise back from some expression (like <code>api.connect()</code>), you call the Promise's <code>then</code> method and pass in a callback function. Passing a function as an argument is conventional in JavaScript, taking advantage of how JavaScript functions are <a href="https://en.wikipedia.org/wiki/First-class_function">first-class objects</a>.</p>
|
||||
<p>When a Promise finishes with its asynchronous operations, the Promise runs the callback function you passed it. The return value from the <code>then</code> method is another Promise object, so you can "chain" that into another <code>then</code> method, or the Promise's <code>catch</code> method, which also takes a callback. The callback you pass to <code>catch</code> gets called if something goes wrong.</p>
|
||||
<p>Finally, we have more new ECMAScript 6 syntax - an <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions">arrow function</a>. Arrow functions are a shorter way of defining anonymous functions. This is convenient for defining lots of one-off functions as callbacks. The syntax <code>()=> {...}</code> is mostly equivalent to <code>function() {...}</code>. If you want an anonymous function with one parameter, you can use a syntax like <code>info => {...}</code> instead, which is almost the same as <code>function(info) {...}</code> syntax.</p>
|
||||
<h3 id="custom-code">Custom code</h3>
|
||||
<pre><code> /* begin custom code ------------------------------------ */
|
||||
const myAddress = 'rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn';
|
||||
|
||||
console.log('getting account info for', myAddress);
|
||||
return api.getAccountInfo(myAddress);
|
||||
|
||||
}).then(info => {
|
||||
console.log(info);
|
||||
console.log('getAccountInfo done');
|
||||
|
||||
/* end custom code -------------------------------------- */
|
||||
</code></pre>
|
||||
<p>This is the part that you change to do whatever you want the script to do.</p>
|
||||
<p>The example code looks up an XRP Ledger account by its address. Try running the code with different addresses to see different results.</p>
|
||||
<p>The <code>console.log()</code> function is built into both Node.js and web browsers, and writes out to the console. This example includes lots of console output to make it easier to understand what the code is doing.</p>
|
||||
<p>Keep in mind that the example code starts in the middle of a callback function (called when RippleAPI finishes connecting). That function calls RippleAPI's <a href="reference-rippleapi.html#getaccountinfo"><code>getAccountInfo</code></a> method, and returns the results.</p>
|
||||
<p>The <code>getAccountInfo</code> API method returns another Promise, so the line <code>}).then( info => {</code> defines another anonymous callback function to run when this Promise's asynchronous work is done. Unlike the previous case, this callback function takes one argument, called <code>info</code>, which holds the asynchronous return value from the <code>getAccountInfo</code> API method. The rest of this callback function outputs that return value to the console.</p>
|
||||
<h3 id="cleanup">Cleanup</h3>
|
||||
<pre><code>}).then(() => {
|
||||
return api.disconnect();
|
||||
}).then(() => {
|
||||
console.log('done and disconnected.');
|
||||
}).catch(console.error);
|
||||
</code></pre>
|
||||
<p>The rest of the sample code is mostly more <a href="reference-rippleapi.html#boilerplate">boilerplate code</a>. The first line ends the previous callback function, then chains to another callback to run when it ends. That method disconnects cleanly from the XRP Ledger, and has yet another callback which writes to the console when it finishes. If your script waits on <a href="reference-rippleapi.html#api-events">RippleAPI events</a>, do not disconnect until you are done waiting for events.</p>
|
||||
<p>The <code>catch</code> method ends this Promise chain. The callback provided here runs if any of the Promises or their callback functions encounters an error. In this case, we pass the standard <code>console.error</code> function, which writes to the console, instead of defining a custom callback. You could define a smarter callback function here to intelligently catch certain error types.</p>
|
||||
<h1 id="waiting-for-validation">Waiting for Validation</h1>
|
||||
<p>One of the biggest challenges in using the XRP Ledger (or any decentralized system) is knowing the final, immutable transaction results. Even if you <a href="tutorial-reliable-transaction-submission.html">follow the best practices</a> you still have to wait for the <a href="https://ripple.com/build/ripple-ledger-consensus-process/">consensus process</a> to finally accept or reject your transaction. The following example code demonstrates how to wait for the final outcome of a transaction:</p>
|
||||
<pre><code>'use strict';
|
||||
/* import RippleAPI and support libraries */
|
||||
const RippleAPI = require('ripple-lib').RippleAPI;
|
||||
const assert = require('assert');
|
||||
|
||||
/* Credentials of the account placing the order */
|
||||
const myAddr = 'rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn';
|
||||
const mySecret = 's████████████████████████████';
|
||||
|
||||
/* Define the order to place here */
|
||||
const myOrder = {
|
||||
'direction': 'buy',
|
||||
'quantity': {
|
||||
'currency': 'FOO',
|
||||
'counterparty': 'rUpy3eEg8rqjqfUoLeBnZkscbKbFsKXC3v',
|
||||
'value': '100'
|
||||
},
|
||||
'totalPrice': {
|
||||
'currency': 'XRP',
|
||||
'value': '1000'
|
||||
}
|
||||
};
|
||||
|
||||
/* Milliseconds to wait between checks for a new ledger. */
|
||||
const INTERVAL = 1000;
|
||||
/* Instantiate RippleAPI. Uses s2 (full history server) */
|
||||
const api = new RippleAPI({server: 'wss://s2.ripple.com'});
|
||||
/* Number of ledgers to check for valid transaction before failing */
|
||||
const ledgerOffset = 5;
|
||||
const myInstructions = {maxLedgerVersionOffset: ledgerOffset};
|
||||
|
||||
|
||||
/* Verify a transaction is in a validated XRP Ledger version */
|
||||
function verifyTransaction(hash, options) {
|
||||
console.log('Verifing Transaction');
|
||||
return api.getTransaction(hash, options).then(data => {
|
||||
console.log('Final Result: ', data.outcome.result);
|
||||
console.log('Validated in Ledger: ', data.outcome.ledgerVersion);
|
||||
console.log('Sequence: ', data.sequence);
|
||||
return data.outcome.result === 'tesSUCCESS';
|
||||
}).catch(error => {
|
||||
/* If transaction not in latest validated ledger,
|
||||
try again until max ledger hit */
|
||||
if (error instanceof api.errors.PendingLedgerVersionError) {
|
||||
return new Promise((resolve, reject) => {
|
||||
setTimeout(() => verifyTransaction(hash, options)
|
||||
.then(resolve, reject), INTERVAL);
|
||||
});
|
||||
}
|
||||
return error;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/* Function to prepare, sign, and submit a transaction to the XRP Ledger. */
|
||||
function submitTransaction(lastClosedLedgerVersion, prepared, secret) {
|
||||
const signedData = api.sign(prepared.txJSON, secret);
|
||||
return api.submit(signedData.signedTransaction).then(data => {
|
||||
console.log('Tentative Result: ', data.resultCode);
|
||||
console.log('Tentative Message: ', data.resultMessage);
|
||||
/* If transaction was not successfully submitted throw error */
|
||||
assert.strictEqual(data.resultCode, 'tesSUCCESS');
|
||||
/* 'tesSUCCESS' means the transaction is being considered for the next ledger, and requires validation. */
|
||||
|
||||
/* If successfully submitted, begin validation workflow */
|
||||
const options = {
|
||||
minLedgerVersion: lastClosedLedgerVersion,
|
||||
maxLedgerVersion: prepared.instructions.maxLedgerVersion
|
||||
};
|
||||
return new Promise((resolve, reject) => {
|
||||
setTimeout(() => verifyTransaction(signedData.id, options)
|
||||
.then(resolve, reject), INTERVAL);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
api.connect().then(() => {
|
||||
console.log('Connected');
|
||||
return api.prepareOrder(myAddr, myOrder, myInstructions);
|
||||
}).then(prepared => {
|
||||
console.log('Order Prepared');
|
||||
return api.getLedger().then(ledger => {
|
||||
console.log('Current Ledger', ledger.ledgerVersion);
|
||||
return submitTransaction(ledger.ledgerVersion, prepared, mySecret);
|
||||
});
|
||||
}).then(() => {
|
||||
api.disconnect().then(() => {
|
||||
console.log('api disconnected');
|
||||
process.exit();
|
||||
});
|
||||
}).catch(console.error);
|
||||
</code></pre>
|
||||
<p>This code creates and submits an order transaction, although the same principles apply to other types of transactions as well. After submitting the transaction, the code uses a new Promise, which queries the ledger again after using setTimeout to wait a fixed amount of time, to see if the transaction has been verified. If it hasn't been verified, the process repeats until either the transaction is found in a validated ledger or the returned ledger is higher than the LastLedgerSequence parameter.</p>
|
||||
<p>In rare cases (particularly with a large delay or a loss of power), the <code>rippled</code> server may be missing a ledger version between when you submitted the transaction and when you determined that the network has passed the <code>maxLedgerVersion</code>. In this case, you cannot be definitively sure whether the transaction has failed, or has been included in one of the missing ledger versions. RippleAPI returns <code>MissingLedgerHistoryError</code> in this case.</p>
|
||||
<p>If you are the administrator of the <code>rippled</code> server, you can <a href="reference-rippled.html#ledger-request">manually request the missing ledger(s)</a>. Otherwise, you can try checking the ledger history using a different server. (Ripple runs a public full-history server at <code>s2.ripple.com</code> for this purpose.)</p>
|
||||
<p>See <a href="tutorial-reliable-transaction-submission.html">Reliable Transaction Submission</a> for a more thorough explanation.</p>
|
||||
<h1 id="rippleapi-in-web-browsers">RippleAPI in Web Browsers</h1>
|
||||
<p>RippleAPI can also be used in a web browser if you compile a browser-compatible version and include <a href="https://www.npmjs.com/package/lodash">lodash</a> as a dependency before the RippleAPI script.</p>
|
||||
<h2 id="build-instructions">Build Instructions</h2>
|
||||
<p>To use RippleAPI in a browser, you need to build a browser-compatible version. The following process compiles RippleAPI into a single JavaScript file you can include in a webpage.</p>
|
||||
<h4 id="1-download-a-copy-of-the-rippleapi-git-repository">1. Download a copy of the RippleAPI git repository.</h4>
|
||||
<p>If you have <a href="https://git-scm.com/book/en/v2/Getting-Started-Installing-Git">Git</a> installed, you can clone the repository and check out the <strong>release</strong> branch, which always has the latest official release:</p>
|
||||
<pre><code>git clone https://github.com/ripple/ripple-lib.git
|
||||
cd ripple-lib
|
||||
git checkout release
|
||||
</code></pre>
|
||||
<p>Alternatively, you can download an archive (.zip or .tar.gz) of a specific release from the <a href="https://github.com/ripple/ripple-lib/releases">RippleAPI releases page</a> and extract it.</p>
|
||||
<h4 id="2-install-dependencies-using-npm">2. Install dependencies using NPM</h4>
|
||||
<p>You need to have <a href="#install-nodejs-and-npm">NPM (Node.js Package Manager) installed</a> first.</p>
|
||||
<p>Then, from within the <code>ripple-lib</code> directory, you can use NPM to install all the necessary dependencies:</p>
|
||||
<pre><code>npm install
|
||||
</code></pre>
|
||||
<p>(We recommend <em>not</em> using <code>npm -g</code> to install dependencies globally.)</p>
|
||||
<p>This can take a while, and may include some warnings. The following warnings are benign and do not indicate a problem:</p>
|
||||
<pre><code>npm WARN optional Skipping failed optional dependency /chokidar/fsevents:
|
||||
npm WARN notsup Not compatible with your operating system or architecture: fsevents@1.0.6
|
||||
</code></pre>
|
||||
<h4 id="3-use-gulp-to-build-a-single-javascript-output">3. Use Gulp to build a single JavaScript output</h4>
|
||||
<p>RippleAPI comes with code to use the <a href="http://gulpjs.com/">gulp</a> package to compile all its source code into browser-compatible JavaScript files. Gulp is automatically installed as one of the dependencies, so all you have to do is run it. RippleAPI's configuration makes this easy:</p>
|
||||
<pre><code>npm run build
|
||||
</code></pre>
|
||||
<p>Output:</p>
|
||||
<pre><code>> ripple-lib@0.16.5 build /home/username/ripple-lib
|
||||
> gulp
|
||||
|
||||
[15:22:30] Using gulpfile /home/username/ripple-lib/Gulpfile.js
|
||||
[15:22:30] Starting 'build'...
|
||||
[15:22:30] Starting 'build-debug'...
|
||||
[15:22:42] Finished 'build' after 12 s
|
||||
[15:22:42] Starting 'build-min'...
|
||||
[15:22:42] Finished 'build-debug' after 12 s
|
||||
[15:22:51] Finished 'build-min' after 9.83 s
|
||||
[15:22:51] Starting 'default'...
|
||||
[15:22:51] Finished 'default' after 4.58 μs
|
||||
</code></pre>
|
||||
<p>This may take a while. At the end, the build process creates a new <code>build/</code> folder, which contains the files you want.</p>
|
||||
<p>The file <code>build/ripple-<VERSION NUMBER>.js</code> is a straight export of RippleAPI (whatever version you built) ready to be used in browsers. The file ending in <code>-min.js</code> is the same thing, but with the content <a href="https://en.wikipedia.org/wiki/Minification_%28programming%29">minified</a> for faster loading.</p>
|
||||
<h2 id="example-browser-usage">Example Browser Usage</h2>
|
||||
<p>The following HTML file demonstrates basic usage of the browser version of RippleAPI to connect to a public <code>rippled</code> server and report information about that server. Instead of using Node.js's "require" syntax, the browser version creates a global variable named <code>ripple</code>, which contains the <code>RippleAPI</code> class.</p>
|
||||
<p>To use this example, you must first <a href="#build-instructions">build RippleAPI</a> and then copy one of the resulting output files to the same folder as this HTML file. (You can use either the minified or full-size version.) Change the first <code><script></code> tag in this example to use the correct file name for the version of RippleAPI you built.</p>
|
||||
<p><a href="https://github.com/ripple/ripple-dev-portal/blob/master/content/code_samples/rippleapi_quickstart/browser-demo.html" title="Source on GitHub"><strong>browser-demo.html:</strong></a></p>
|
||||
<pre><code><!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.15.0/lodash.js"></script>
|
||||
<script src="ripple-0.17.7-min.js"></script>
|
||||
<script>
|
||||
console.log(ripple);
|
||||
var api = new ripple.RippleAPI({server:'wss://s1.ripple.com/'});
|
||||
api.connect().then(function() {
|
||||
return api.getServerInfo();
|
||||
}).then(function(server_info) {
|
||||
document.body.innerHTML += "<p>Connected to rippled server!</p>" +
|
||||
" <table>" +
|
||||
" <tr><th>Version</th>" +
|
||||
" <td>" + server_info.buildVersion + "</td></tr>" +
|
||||
" <tr><th>Ledgers available</th>" +
|
||||
" <td>" + server_info.completeLedgers + "</td></tr>" +
|
||||
" <tr><th>hostID</th>" +
|
||||
" <td>" + server_info.hostID + "</td></tr>" +
|
||||
" <tr><th>Most Recent Validated Ledger Seq.</th>" +
|
||||
" <td>" + server_info.validatedLedger.ledgerVersion + "</td></tr>" +
|
||||
" <tr><th>Most Recent Validated Ledger Hash</th>" +
|
||||
" <td>" + server_info.validatedLedger.hash + "</td></tr>" +
|
||||
" <tr><th>Seconds since last ledger validated</th>" +
|
||||
" <td>" + server_info.validatedLedger.age + "</td></tr>" +
|
||||
" </table>";
|
||||
});
|
||||
</script>
|
||||
<style type="text/css">
|
||||
td, th { border: 1px solid black; padding: 5px; }
|
||||
table { border-collapse: collapse; }
|
||||
</style>
|
||||
</head>
|
||||
<body></body>
|
||||
</html>
|
||||
</code></pre>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<footer class="content-info" role="contentinfo">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-sm-12 absolute_bottom_footer">
|
||||
<div class="col-sm-8">
|
||||
<span>© 2013 - 2017 Ripple Labs, Inc. All Rights Reserved.</span>
|
||||
<span><a href="/terms-of-use/">Terms</a></span>
|
||||
<span><a href="/privacy-policy/">Privacy</a></span>
|
||||
</div>
|
||||
</div><!-- /.absolute_bottom_footer -->
|
||||
|
||||
</div><!-- /.row -->
|
||||
</div><!-- /.container -->
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,498 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<meta name="viewport" content="width=device-width">
|
||||
|
||||
<title>rippled Setup - Ripple Developer Portal</title>
|
||||
|
||||
<!-- favicon -->
|
||||
<link rel="icon" href="favicon.ico" type="image/x-icon">
|
||||
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon">
|
||||
|
||||
<!-- jQuery -->
|
||||
<script src="assets/vendor/jquery-1.11.1.min.js"></script>
|
||||
|
||||
<!-- Custom Stylesheets. ripple.css includes bootstrap, font stuff -->
|
||||
<link href="assets/css/ripple.css" rel="stylesheet" />
|
||||
<link href="assets/css/devportal.css" rel="stylesheet" />
|
||||
|
||||
<!-- Bootstrap JS -->
|
||||
<script src="assets/vendor/bootstrap.min.js"></script>
|
||||
|
||||
|
||||
<!-- syntax highlighting -->
|
||||
<link rel="stylesheet" href="assets/vendor/docco.min.css" />
|
||||
<script src="assets/vendor/highlight.min.js"></script>
|
||||
|
||||
<!-- syntax selection js -->
|
||||
<script src="assets/js/multicodetab.js"></script>
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
$(".multicode").minitabs();
|
||||
hljs.initHighlighting();
|
||||
make_code_expandable();
|
||||
});
|
||||
</script>
|
||||
|
||||
<script src="assets/js/expandcode.js"></script>
|
||||
<script src="assets/js/fixsidebarscroll.js"></script>
|
||||
|
||||
<!-- fontawesome icons -->
|
||||
<link rel="stylesheet" href="assets/vendor/fontawesome/css/font-awesome.min.css" />
|
||||
|
||||
</head>
|
||||
|
||||
<body class="page page-template page-template-template-dev-portal page-template-template-dev-portal-php sidebar-primary wpb-js-composer js-comp-ver-3.6.2 vc_responsive">
|
||||
<header role="banner" class="banner navbar navbar-default navbar-fixed-top initial_header">
|
||||
<div class="container">
|
||||
<div class="navbar-header">
|
||||
<a href="index.html" class="navbar-brand"><img src="assets/img/ripple-logo-color.png" class="logo"></a>
|
||||
</div><!-- /.navbar-header -->
|
||||
<div class="nav">
|
||||
<div class="draft-warning">DRAFT PAGE</div>
|
||||
</div><!-- /.nav -->
|
||||
|
||||
</div><!-- /.container -->
|
||||
|
||||
<div class="subnav dev_nav">
|
||||
<div class="container">
|
||||
<ul id="menu-dev-menu" class="menu">
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">References <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="reference-rippleapi.html">RippleAPI</a></li>
|
||||
<li><a href="reference-rippled.html">rippled</a></li>
|
||||
<li><a href="reference-transaction-format.html">Transaction Format</a></li>
|
||||
<li><a href="reference-ledger-format.html">Ledger Format</a></li>
|
||||
<li><a href="reference-data-api.html">Ripple Data API v2</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorials <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="tutorial-multisign.html">How to Multi-Sign</a></li>
|
||||
<li><a href="tutorial-paychan.html">Payment Channels Tutorial</a></li>
|
||||
<li><a href="concept-issuing-and-operational-addresses.html">Issuing and Operational Addresses</a></li>
|
||||
<li><a href="tutorial-reliable-transaction-submission.html">Reliable Transaction Submission</a></li>
|
||||
<li><a href="tutorial-rippleapi-beginners-guide.html">RippleAPI Beginners Guide</a></li>
|
||||
<li><a href="tutorial-rippled-setup.html">rippled Setup</a></li>
|
||||
<li><a href="tutorial-gateway-guide.html">Gateway Guide</a></li>
|
||||
<li><a href="tutorial-listing-xrp.html">Listing XRP as an Exchange</a></li>
|
||||
<li><a href="tutorial-escrow.html">Escrow Tutorials</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Features <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="concept-accounts.html">Accounts</a></li>
|
||||
<li><a href="concept-amendments.html">Amendments</a></li>
|
||||
<li><a href="concept-consensus.html">Consensus Process</a></li>
|
||||
<li><a href="concept-reaching-consensus.html">Reaching Consensus in the XRP Ledger</a></li>
|
||||
<li><a href="concept-fee-voting.html">Fee Voting</a></li>
|
||||
<li><a href="concept-fees.html">Fees (Disambiguation)</a></li>
|
||||
<li><a href="concept-freeze.html">Freeze</a></li>
|
||||
<li><a href="concept-partial-payments.html">Partial Payments</a></li>
|
||||
<li><a href="concept-paths.html">Paths</a></li>
|
||||
<li><a href="concept-reserves.html">Reserves</a></li>
|
||||
<li><a href="concept-stand-alone-mode.html">Stand-Alone Mode</a></li>
|
||||
<li><a href="concept-transaction-cost.html">Transaction Cost</a></li>
|
||||
<li><a href="concept-transfer-fees.html">Transfer Fees</a></li>
|
||||
<li><a href="concept-noripple.html">Understanding the NoRipple flag</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Gateway Bulletins <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="gb-2015-06.html">GB-2015-06: Corrections to Autobridging</a></li>
|
||||
<li><a href="gb-2015-05.html">GB-2015-05: Historical Ledger Query Migration</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">API Tools <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="ripple-api-tool.html">WebSocket API Tool</a></li>
|
||||
<li><a href="data-api-v2-tool.html">Data API v2 Tool</a></li>
|
||||
<li><a href="tool-jsonrpc.html">rippled JSON-RPC Tool</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li><a href="https://github.com/ripple/ripple-dev-portal" title="GitHub">Site Source</a></li>
|
||||
</ul><!-- /#dev-menu -->
|
||||
</div><!-- /.subnav .container -->
|
||||
</div><!-- /.subnav -->
|
||||
</header>
|
||||
|
||||
|
||||
<div class="wrap container" role="document">
|
||||
<aside class="sidebar" role="complementary">
|
||||
<div class="dev_nav_wrapper">
|
||||
<div id="cont">
|
||||
<h5>In this category:</h5>
|
||||
<ul class="dev_nav_sidebar">
|
||||
<li class="level-1"><a href="index.html">Category: Tutorials</a></li>
|
||||
<li class="level-2"><a href="tutorial-multisign.html">How to Multi-Sign</a></li>
|
||||
<li class="level-2"><a href="tutorial-paychan.html">Payment Channels Tutorial</a></li>
|
||||
<li class="level-2"><a href="concept-issuing-and-operational-addresses.html">Issuing and Operational Addresses</a></li>
|
||||
<li class="level-2"><a href="tutorial-reliable-transaction-submission.html">Reliable Transaction Submission</a></li>
|
||||
<li class="level-2"><a href="tutorial-rippleapi-beginners-guide.html">RippleAPI Beginners Guide</a></li>
|
||||
<li class="level-2"><a href="tutorial-rippled-setup.html">rippled Setup</a></li>
|
||||
<li class="level-2"><a href="tutorial-gateway-guide.html">Gateway Guide</a></li>
|
||||
<li class="level-2"><a href="tutorial-listing-xrp.html">Listing XRP as an Exchange</a></li>
|
||||
<li class="level-2"><a href="tutorial-escrow.html">Escrow Tutorials</a></li>
|
||||
</ul>
|
||||
<hr />
|
||||
<h5>In this page:</h5>
|
||||
<ul class="dev_nav_sidebar" id="dactyl_toc_sidebar">
|
||||
<li class="level-1"><a href="#operating-rippled-servers">Operating rippled Servers</a></li>
|
||||
<li class="level-2"><a href="#types-of-rippled-servers">Types of rippled Servers</a></li>
|
||||
<li class="level-2"><a href="#reasons-to-run-a-stock-server">Reasons to Run a Stock Server</a></li>
|
||||
<li class="level-2"><a href="#reasons-to-run-a-validator">Reasons to Run a Validator</a></li>
|
||||
<li class="level-3"><a href="#properties-of-a-good-validator">Properties of a Good Validator</a></li>
|
||||
<li class="level-1"><a href="#installing-rippled">Installing rippled</a></li>
|
||||
<li class="level-2"><a href="#system-requirements">System Requirements</a></li>
|
||||
<li class="level-2"><a href="#installation-on-centosred-hat-with-yum">Installation on CentOS/Red Hat with yum</a></li>
|
||||
<li class="level-2"><a href="#installation-on-ubuntu-with-alien">Installation on Ubuntu with alien</a></li>
|
||||
<li class="level-2"><a href="#postinstall">Postinstall</a></li>
|
||||
<li class="level-2"><a href="#updating-rippled">Updating rippled</a></li>
|
||||
<li class="level-3"><a href="#automatic-update-on-centosred-hat">Automatic Update on CentOS/Red Hat</a></li>
|
||||
<li class="level-3"><a href="#manual-update-on-centosred-hat">Manual Update on CentOS/Red Hat</a></li>
|
||||
<li class="level-3"><a href="#manual-update-on-ubuntu">Manual Update on Ubuntu</a></li>
|
||||
<li class="level-1"><a href="#running-a-validator">Running a Validator</a></li>
|
||||
<li class="level-2"><a href="#validator-setup">Validator Setup</a></li>
|
||||
<li class="level-2"><a href="#public-facing-server">Public-Facing Server</a></li>
|
||||
<li class="level-2"><a href="#domain-verification">Domain Verification</a></li>
|
||||
<li class="level-1"><a href="#additional-configuration">Additional Configuration</a></li>
|
||||
<li class="level-2"><a href="#parallel-networks">Parallel Networks</a></li>
|
||||
<li class="level-3"><a href="#parallel-networks-and-consensus">Parallel Networks and Consensus</a></li>
|
||||
<li class="level-2"><a href="#clustering">Clustering</a></li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
<main class="main" role="main">
|
||||
<div class='content'>
|
||||
<h1 id="operating-rippled-servers">Operating rippled Servers</h1>
|
||||
<p>The core server of the XRP Ledger peer-to-peer network is <a href="reference-rippled.html"><code>rippled</code></a>. Anyone can run their own <code>rippled</code> server that follows the network and keeps a complete copy of the XRP Ledger. You can even have your server take part in the consensus process.</p>
|
||||
<p>This page contains instructions for:</p>
|
||||
<ul>
|
||||
<li><a href="#installing-rippled">Installing <code>rippled</code></a></li>
|
||||
<li><a href="#running-a-validator">Participating in the Consensus Process</a></li>
|
||||
</ul>
|
||||
<h2 id="types-of-rippled-servers">Types of rippled Servers</h2>
|
||||
<p>The <code>rippled</code> server software can run in several modes depending on its configuration, including:</p>
|
||||
<ul>
|
||||
<li>Stock server - follows the network with a local copy of the ledger.</li>
|
||||
<li>Validating server, or <em>validator</em> for short - participates in consensus.</li>
|
||||
<li><code>rippled</code> server in stand-alone mode - for testing. Does not communicate to other <code>rippled</code> servers.</li>
|
||||
</ul>
|
||||
<p>You can also run the <code>rippled</code> executable as a client application for accessing <a href="reference-rippled.html"><code>rippled</code> APIs</a> locally. (Two instances of the same binary can run side-by-side in this case; one as a server, and the other running briefly as a client and then terminating.)</p>
|
||||
<h2 id="reasons-to-run-a-stock-server">Reasons to Run a Stock Server</h2>
|
||||
<p>There are lots of reasons you might want to run your own <code>rippled</code> server, but most of them can be summarized as: you can trust your own server, you have control over its workload, and you're not at the mercy of others to decide when and how you can access it. Of course, you must practice good network security to protect your server from malicious hackers.</p>
|
||||
<p>You need to trust the <code>rippled</code> you use. If you connect to a malicious server, there are many ways that it can take advantage of you or cause you to lose money. For example:</p>
|
||||
<ul>
|
||||
<li>A malicious server could report that you were paid when no such payment was made.</li>
|
||||
<li>It could selectively show or hide payment paths and currency exchange offers to guarantee its own profit while not providing you the best deal.</li>
|
||||
<li>If you sent it your address's secret key, it could make arbitrary transactions on your behalf, and even transfer or destroy all the money your address holds.</li>
|
||||
</ul>
|
||||
<p>Additionally, running your own server gives you admin control over it, which allows you to run important admin-only and load-intensive commands. If you use a shared server, you have to worry about other users of the same server competing with you for the server's computing power. Many of the commands in the WebSocket API can put a lot of strain on the server, so <code>rippled</code> has the option to scale back its responses when it needs to. If you share a server with others, you may not always get the best results possible.</p>
|
||||
<p>Finally, if you run a validating server, you can use a stock server as a proxy to the public network while keeping your validating server on a private subnet only accessible to the outside world through the stock server. This makes it more difficult to compromise the integrity of your validating server.</p>
|
||||
<h2 id="reasons-to-run-a-validator">Reasons to Run a Validator</h2>
|
||||
<p>The robustness of the XRP Ledger depends on an interconnected web of validators who each trust a few other validators <em>not to collude</em>. The more operators with different interests there are who run validators, the more certain each member of the network can be that it continues to run impartially. If you or your organization relies on the XRP Ledger, it is in your interest to contribute to the consensus process.</p>
|
||||
<p>Not all <code>rippled</code> servers need to be validators: trusting more servers from the same operator does not offer better protection against collusion. An organization might run validators in multiple regions for redundancy in case of natural disasters and other emergencies.</p>
|
||||
<p>If your organization runs a validating server, you may also run one or more stock servers, to balance the computing load of API access, or as a proxy between your validation server and the outside network.</p>
|
||||
<h3 id="properties-of-a-good-validator">Properties of a Good Validator</h3>
|
||||
<p>There are several properties that define a good validator. The more of these properties your server embodies, the more reason others have to include your server in their list of trusted validators:</p>
|
||||
<ul>
|
||||
<li><strong>Availability</strong>. An ideal validator should always be running, submitting validation votes for every proposed ledger.<ul>
|
||||
<li>Strive for 100% uptime.</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><strong>Agreement</strong>. A validator's votes should match the outcome of the consensus process as often as possible. To do otherwise could indicate that the validator's software is outdated, buggy, or intentionally biased.<ul>
|
||||
<li>Always run the latest <code>rippled</code> release without modifications.</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><strong>Timeliness</strong>. A validator's votes should arrive quickly, and not after a consensus round has already finished.<ul>
|
||||
<li>A fast internet connection helps with this.</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><strong>Identified</strong>. It should be clear who runs the validator. Ideally, a list of trusted validators should include validators operated by different owners in multiple legal jurisdictions and geographic areas, to reduce the chance that any localized events could interfere with the validator's impartial operation.<ul>
|
||||
<li>Setting up <a href="#domain-verification">Domain Verification</a> is a good start.</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<p>At present, Ripple (the company) cannot recommend any validators aside from the 5 core validators run by Ripple: these validators are included in the default <code>rippled</code> configuration. However, we are collecting data on other validators and building tools to report on their performance. For metrics on validators, see <a href="https://validators.ripple.com">validators.ripple.com</a>.</p>
|
||||
<h1 id="installing-rippled">Installing rippled</h1>
|
||||
<p>For development, you can <a href="https://wiki.ripple.com/Rippled_build_instructions">compile <code>rippled</code> from source</a>.</p>
|
||||
<p>Production <code>rippled</code> instances can <a href="#installation-on-centosred-hat-with-yum">use Ripple's binary executable</a>, available from the Ripple <a href="https://en.wikipedia.org/wiki/Yellowdog_Updater,_Modified">yum</a> repository.</p>
|
||||
<h2 id="system-requirements">System Requirements</h2>
|
||||
<p>A <code>rippled</code> server should run comfortably on commodity hardware, to make it inexpensive to participate in the network. At present, we recommend the following:</p>
|
||||
<ul>
|
||||
<li>Operating System:<ul>
|
||||
<li>Production: CentOS or RedHat Enterprise Linux (latest release) or Ubuntu (15.04+) supported</li>
|
||||
<li>Development: Mac OS X, Windows (64-bit), or most Linux distributions</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>CPU: 64-bit x86_64, 2+ cores</li>
|
||||
<li>Disk: Minimum 50GB SSD recommended (500+ IOPS, more is better) for the database partition</li>
|
||||
<li>RAM: 4+GB</li>
|
||||
</ul>
|
||||
<p>Amazon EC2's m3.large VM size may be appropriate depending on your workload. (Validating servers need more resources.)</p>
|
||||
<p>Naturally, a fast network connection is preferable.</p>
|
||||
<h2 id="installation-on-centosred-hat-with-yum">Installation on CentOS/Red Hat with yum</h2>
|
||||
<p>This section assumes that you are using CentOS 7 or Red Hat Enterprise Linux 7.</p>
|
||||
<ol>
|
||||
<li>
|
||||
<p>Install the Ripple RPM repository:</p>
|
||||
<pre><code>$ sudo rpm -Uvh https://mirrors.ripple.com/ripple-repo-el7.rpm
|
||||
</code></pre>
|
||||
</li>
|
||||
<li>
|
||||
<p>Install the <code>rippled</code> software package:</p>
|
||||
<pre><code>$ sudo yum install --enablerepo=ripple-stable rippled
|
||||
</code></pre>
|
||||
</li>
|
||||
<li>
|
||||
<p>Configure the <code>rippled</code> service to start on system boot:</p>
|
||||
<pre><code>$ sudo systemctl enable rippled.service
|
||||
</code></pre>
|
||||
</li>
|
||||
<li>
|
||||
<p>Start the <code>rippled</code> service</p>
|
||||
<pre><code>$ sudo systemctl start rippled.service
|
||||
</code></pre>
|
||||
</li>
|
||||
</ol>
|
||||
<h2 id="installation-on-ubuntu-with-alien">Installation on Ubuntu with alien</h2>
|
||||
<p>This section assumes that you are using Ubuntu 15.04 or later.</p>
|
||||
<ol>
|
||||
<li>
|
||||
<p>Install yum-utils and alien:</p>
|
||||
<pre><code>$ sudo apt-get update
|
||||
$ sudo apt-get install yum-utils alien
|
||||
</code></pre>
|
||||
</li>
|
||||
<li>
|
||||
<p>Install the Ripple RPM repository:</p>
|
||||
<pre><code>$ sudo rpm -Uvh https://mirrors.ripple.com/ripple-repo-el7.rpm
|
||||
</code></pre>
|
||||
</li>
|
||||
<li>
|
||||
<p>Download the <code>rippled</code> software package:</p>
|
||||
<pre><code>$ yumdownloader --enablerepo=ripple-stable --releasever=el7 rippled
|
||||
</code></pre>
|
||||
</li>
|
||||
<li>
|
||||
<p>Verify the signature on the <code>rippled</code> software package:</p>
|
||||
<pre><code>$ sudo rpm --import https://mirrors.ripple.com/rpm/RPM-GPG-KEY-ripple-release && rpm -K rippled*.rpm
|
||||
</code></pre>
|
||||
</li>
|
||||
<li>
|
||||
<p>Install the <code>rippled</code> software package:</p>
|
||||
<pre><code>$ sudo alien -i --scripts rippled*.rpm && rm rippled*.rpm
|
||||
</code></pre>
|
||||
</li>
|
||||
<li>
|
||||
<p>Configure the <code>rippled</code> service to start on system boot:</p>
|
||||
<pre><code>$ sudo systemctl enable rippled.service
|
||||
</code></pre>
|
||||
</li>
|
||||
<li>
|
||||
<p>Start the <code>rippled</code> service</p>
|
||||
<pre><code>$ sudo systemctl start rippled.service
|
||||
</code></pre>
|
||||
</li>
|
||||
</ol>
|
||||
<h2 id="postinstall">Postinstall</h2>
|
||||
<p>It can take several minutes for <code>rippled</code> to sync with the rest of the network, during which time it outputs warnings about missing ledgers. After that, you have a fully functional stock <code>rippled</code> server that you can use for local signing and API access to the XRP Ledger.</p>
|
||||
<p><a href="reference-rippled.html#list-of-public-commands">rippled commands</a> can be run with:</p>
|
||||
<pre><code> $ /opt/ripple/bin/rippled <command>
|
||||
</code></pre>
|
||||
<h2 id="updating-rippled">Updating rippled</h2>
|
||||
<p>You can subscribe to the <a href="https://groups.google.com/forum/#!forum/ripple-server">rippled Google Group</a> to receive notifications of new <code>rippled</code> releases.</p>
|
||||
<h3 id="automatic-update-on-centosred-hat">Automatic Update on CentOS/Red Hat</h3>
|
||||
<p>Automatic rippled updates can be enabled with a one-time Cron configuration:</p>
|
||||
<ol>
|
||||
<li>
|
||||
<p>Check that <code>/opt/ripple/bin/update-rippled.sh</code> exists. If it does not, <a href="#manual-update-on-centosred-hat">update manually</a>.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Install <code>crond</code>:</p>
|
||||
<pre><code>$ sudo yum install cronie
|
||||
</code></pre>
|
||||
</li>
|
||||
<li>
|
||||
<p>Open the crontab file for editing</p>
|
||||
<pre><code>$ sudo crontab -e
|
||||
</code></pre>
|
||||
</li>
|
||||
<li>
|
||||
<p>Add the following to the crontab file. Be sure to add a blank line at the end of the file.</p>
|
||||
<pre><code>RANDOM_DELAY=59
|
||||
0 * * * * /opt/ripple/bin/update-rippled.sh
|
||||
</code></pre>
|
||||
</li>
|
||||
</ol>
|
||||
<p>The script updates the installed <code>rippled</code> package within an hour of each new release.</p>
|
||||
<h3 id="manual-update-on-centosred-hat">Manual Update on CentOS/Red Hat</h3>
|
||||
<p>Run the following commands to update to the latest release of <code>rippled</code>:</p>
|
||||
<pre><code> $ sudo rpm -Uvh --replacepkgs https://mirrors.ripple.com/ripple-repo-el7.rpm
|
||||
$ sudo yum update --enablerepo=ripple-stable rippled
|
||||
$ sudo systemctl daemon-reload
|
||||
$ sudo service rippled restart
|
||||
</code></pre>
|
||||
<h3 id="manual-update-on-ubuntu">Manual Update on Ubuntu</h3>
|
||||
<p>Run the following commands to update to the latest release of <code>rippled</code>:</p>
|
||||
<pre><code> $ sudo rpm -Uvh --replacepkgs https://mirrors.ripple.com/ripple-repo-el7.rpm
|
||||
$ yumdownloader --enablerepo=ripple-stable --releasever=el7 rippled
|
||||
$ rpm -K rippled*.rpm
|
||||
$ sudo alien -i --scripts rippled*.rpm
|
||||
$ sudo systemctl daemon-reload
|
||||
$ sudo service rippled restart
|
||||
</code></pre>
|
||||
<h1 id="running-a-validator">Running a Validator</h1>
|
||||
<p>Running a <code>rippled</code> validator that participates in the Consensus process is simple:</p>
|
||||
<ol>
|
||||
<li><a href="#validator-setup">Enable validation</a> on your <code>rippled</code> server.<ul>
|
||||
<li>At first, your server is an <em>untrusted validator</em>. Others can see the validations your server issues, but they disregard them in the consensus process.</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>Share the public key with the public, especially other <code>rippled</code> operators.</li>
|
||||
<li>When other <code>rippled</code> operators add your public key to their list of trusted servers, you have become a <em>trusted validator</em>.<ul>
|
||||
<li>Also see <a href="#properties-of-a-good-validator">Properties of a Good Validator</a> for best practices.</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ol>
|
||||
<h2 id="validator-setup">Validator Setup</h2>
|
||||
<p>The <code>validator-keys</code> tool (included in the <code>rippled</code> RPM) is the recommended means to securely generate and manage your validator keys.</p>
|
||||
<ol>
|
||||
<li>
|
||||
<p><a href="#installing-rippled">Install a <code>rippled</code> server.</a></p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Generate a validator key pair:</p>
|
||||
<pre><code>$ /opt/ripple/bin/validator-keys create_keys
|
||||
</code></pre>
|
||||
<p class="devportal-callout warning"><strong>Warning:</strong> Store the generated <code>validator-keys.json</code> key file in a secure but recoverable location, such as an encrypted USB flash drive. Do not modify its contents.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Generate a validator token and edit your <code>rippled.cfg</code> file to add the <code>[validator_token]</code> value.</p>
|
||||
<pre><code>$ /opt/ripple/bin/validator-keys create_token --keyfile /path/to/your/validator-keys.json
|
||||
</code></pre>
|
||||
<p>If you had previously configured your validator without using the <code>validator-keys</code> tool, you will need to also delete the <code>[validation_seed]</code> from your <code>rippled.cfg</code> file. This changes your validator public key.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Start <code>rippled</code>:</p>
|
||||
<pre><code>$ sudo service rippled restart
|
||||
</code></pre>
|
||||
</li>
|
||||
</ol>
|
||||
<p>See <a href="https://github.com/ripple/validator-keys-tool/blob/master/doc/validator-keys-tool-guide.md">the <code>validator-keys-tool</code> GitHub repository</a> for more information about managing validator keys.</p>
|
||||
<h2 id="public-facing-server">Public-Facing Server</h2>
|
||||
<p>To protect a production validator from <a href="https://en.wikipedia.org/wiki/Denial-of-service_attack">DDoS</a> attacks, you can use a stock <code>rippled</code> server as a proxy between the validator and the outside network.</p>
|
||||
<ol>
|
||||
<li>
|
||||
<p><a href="#validator-setup">Set up the <code>rippled</code> validator.</a></p>
|
||||
</li>
|
||||
<li>
|
||||
<p><a href="#installing-rippled">Set up one or more stock <code>rippled</code> servers.</a></p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Configure the validator and stock <code>rippled</code> servers to be <a href="#clustering">clustered</a> with each other.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Make the following configuration changes to your validator:</p>
|
||||
<ul>
|
||||
<li>Copy the <code>[ips_fixed]</code> list and paste it under <code>[ips]</code>. These fields should contain only the IP addresses and ports of the public-facing rippled(s). The validator connects to only these peers.</li>
|
||||
<li>Change <code>[peer_private]</code> to <code>1</code> to prevent its IP address from being forwarded.</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<p>Configure the validator host machine's firewall to only accept inbound connections from its public-facing rippled(s).</p>
|
||||
</li>
|
||||
</ol>
|
||||
<p>Remember to restart <code>rippled</code> for config changes to take effect.</p>
|
||||
<p>Take care not to publish the IP address of your validator.</p>
|
||||
<h2 id="domain-verification">Domain Verification</h2>
|
||||
<p>Network participants are unlikely to trust validators without knowing who is operating them. To address this concern, validator operators can associate their validator with a web domain that they control.</p>
|
||||
<ol>
|
||||
<li>
|
||||
<p>Find your validator public key by running the following on the validator server:</p>
|
||||
<pre><code>$ /opt/ripple/bin/rippled server_info -q | grep pubkey_validator
|
||||
</code></pre>
|
||||
</li>
|
||||
<li>
|
||||
<p>Sign the validator public key (from step 1) using the SSL private key used for your domain. The SSL private key file does not need to be stored on the validator server.</p>
|
||||
<pre><code>$ openssl dgst -sha256 -hex -sign /path/to/your/ssl.key <(echo <your-validator-public-key>)
|
||||
</code></pre>
|
||||
</li>
|
||||
<li>
|
||||
<p>Using <code>validator-keys</code> tool (included in the <code>rippled</code> RPM), sign the domain name:</p>
|
||||
<pre><code>$ /opt/ripple/bin/validator-keys --keyfile /path/to/your/validator-keys.json sign <your-domain-name>
|
||||
</code></pre>
|
||||
</li>
|
||||
<li>
|
||||
<p>In order to have the verified validator domain published, email <a href="mailto:validators@ripple.com">validators@ripple.com</a> with both signatures as well as the validator public key and domain name.</p>
|
||||
</li>
|
||||
</ol>
|
||||
<h1 id="additional-configuration">Additional Configuration</h1>
|
||||
<p><code>rippled</code> should connect to the XRP Ledger with the default configuration. However, you can change your settings by editing the <code>rippled.cfg</code> file (located at <code>/opt/ripple/etc/rippled.cfg</code> when installing <code>rippled</code> with yum).</p>
|
||||
<p>See <a href="https://github.com/ripple/rippled/blob/develop/doc/rippled-example.cfg">the <code>rippled</code> GitHub repository</a> for a description of all configuration options.</p>
|
||||
<p>Changes to the <code>[debug_logfile]</code> or <code>[database_path]</code> sections may require you to give the <code>rippled</code> user and group ownership to your new configured path:</p>
|
||||
<pre><code> $ chown -R rippled:rippled <configured path>
|
||||
</code></pre>
|
||||
<p>Restart <code>rippled</code> for any configuration changes to take effect:</p>
|
||||
<pre><code> $ sudo service rippled restart
|
||||
</code></pre>
|
||||
<h2 id="parallel-networks">Parallel Networks</h2>
|
||||
<p>Most of the time, we describe the XRP Ledger as one collective, singular entity -- and that's mostly true. 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.</p>
|
||||
<p>However, sometimes you may want to do tests and experiments without interacting with the core network. That's why Ripple started the <a href="https://ripple.com/build/ripple-test-net/">Ripple Test Net</a>, an "alternate universe" network, which can act as a testing ground for applications and the <code>rippled</code> server itself, without impacting the business operations of everyday XRP Ledger users. The Ripple Test Net (also known as the AltNet) has a separate supply of TestNet-only XRP, which Ripple <a href="https://ripple.com/build/ripple-test-net/">gives away for free</a> to parties interested in developing applications on the Test Net.</p>
|
||||
<p class="devportal-callout caution"><strong>Caution:</strong> Ripple makes no guarantees about the stability of the test network. It has been and continues to be used to test various properties of server configuration, network topology, and network performance.</p>
|
||||
<p>Over time, there may also be smaller, temporary test networks for specific purposes.</p>
|
||||
<h3 id="parallel-networks-and-consensus">Parallel Networks and Consensus</h3>
|
||||
<p>There is no <code>rippled</code> setting that defines which network it uses. Instead, it uses the consensus of validators it trusts to know which ledger to accept as the truth. When different consensus groups of <code>rippled</code> 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.</p>
|
||||
<h2 id="clustering">Clustering</h2>
|
||||
<p>If you are running multiple <code>rippled</code> servers in a single datacenter, you can configure those servers into a cluster to maximize efficiency. Running your <code>rippled</code> servers in a cluster provides the following benefits:</p>
|
||||
<ul>
|
||||
<li>Clustered <code>rippled</code> 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.</li>
|
||||
<li>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.</li>
|
||||
<li>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.</li>
|
||||
</ul>
|
||||
<p>To enable clustering, change the following sections of your <a href="https://github.com/ripple/rippled/blob/d7def5509d8338b1e46c0adf309b5912e5168af0/doc/rippled-example.cfg#L297-L346">config file</a> for each server:</p>
|
||||
<ul>
|
||||
<li>
|
||||
<p>List the IP address and port of each other server under the <code>[ips_fixed]</code> section. The port should be the one from the other servers' <code>protocol = peer</code> setting in their <code>rippled.cfg</code>. Example:</p>
|
||||
<pre><code>[ips_fixed]
|
||||
192.168.0.1 51235
|
||||
192.168.0.2 51235
|
||||
</code></pre>
|
||||
</li>
|
||||
<li>
|
||||
<p>Generate a unique seed (using the <a href="reference-rippled.html#validation-seed"><code>validation_create</code> command</a>) for each of your servers, and configure it under the <code>[node_seed]</code> section. The <code>rippled</code> server uses this key to sign its messages to other servers in the peer-to-peer network.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Add the public keys (for peer communication) of each of your other servers under the <code>[cluster_nodes]</code> section.</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<footer class="content-info" role="contentinfo">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-sm-12 absolute_bottom_footer">
|
||||
<div class="col-sm-8">
|
||||
<span>© 2013 - 2017 Ripple Labs, Inc. All Rights Reserved.</span>
|
||||
<span><a href="/terms-of-use/">Terms</a></span>
|
||||
<span><a href="/privacy-policy/">Privacy</a></span>
|
||||
</div>
|
||||
</div><!-- /.absolute_bottom_footer -->
|
||||
|
||||
</div><!-- /.row -->
|
||||
</div><!-- /.container -->
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user