mirror of
https://github.com/XRPLF/xrpl-dev-portal.git
synced 2025-11-25 22:25:52 +00:00
multi-sign - revisions to tutorial and reorg based on feedback.
This commit is contained in:
@@ -146,6 +146,7 @@
|
|||||||
<ul>
|
<ul>
|
||||||
<li><a href="reference-ledger-format.html#offer">Offers</a> are owned by the account that placed them. An Offer can be automatically removed from the ledger if it is fully consumed or if it is found unfunded during transaction processing. 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#offer">Offers</a> are owned by the account that placed them. An Offer can be automatically removed from the ledger if it is fully consumed or if it is found unfunded during transaction processing. 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 accounts. The owner reserve can apply to one or both of the accounts, depending on whether the fields that account 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 href="reference-ledger-format.html#ripplestate">Trust lines</a> are shared between two accounts. The owner reserve can apply to one or both of the accounts, depending on whether the fields that account 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#directorynode">Owner directories</a> list all the ledger nodes that contribute to an account's owner reserve. However, the owner directory itself does not count towards the reserve.</li>
|
<li><a href="reference-ledger-format.html#directorynode">Owner directories</a> list all the ledger nodes that contribute to an account's owner reserve. However, the owner directory itself does not count towards the reserve.</li>
|
||||||
</ul>
|
</ul>
|
||||||
<h4 id="owner-reserve-edge-cases">Owner Reserve Edge Cases</h4>
|
<h4 id="owner-reserve-edge-cases">Owner Reserve Edge Cases</h4>
|
||||||
|
|||||||
@@ -132,7 +132,7 @@
|
|||||||
<main class="main" role="main">
|
<main class="main" role="main">
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<h1 id="stand-alone-mode">Stand-Alone Mode</h1>
|
<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 Ripple peer-to-peer network, but you can perform most of the same actions on your local server only. Stand-alone provides a method for testing <code>rippled</code> behavior, including the effects of <a href="concept-amendments.html">Amendments</a> before those Amendments have gone into effect across the decentralized network.</p>
|
<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 Ripple 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, including the effects of <a href="concept-amendments.html">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>
|
<p>When you run <code>rippled</code> in stand-alone mode, you have to tell it what ledger version to start from:</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li>Create a <a href="#new-genesis-ledger">new genesis ledger</a> from scratch.</li>
|
<li>Create a <a href="#new-genesis-ledger">new genesis ledger</a> from scratch.</li>
|
||||||
@@ -140,7 +140,7 @@
|
|||||||
</ul>
|
</ul>
|
||||||
<p><strong>Caution:</strong> In stand-alone mode, you must <a href="#advancing-ledgers-in-stand-alone-mode">manually advance the ledger</a>.</p>
|
<p><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>
|
<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 Ripple network. (This is very useful for unit tests, among other things.)</p>
|
<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 Ripple Consensus Ledger. (This is very useful for unit tests, among other things.)</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li>To start <code>rippled</code> in stand-alone mode with a new genesis ledger, use the <code>-a</code> and <code>--start</code> options:</li>
|
<li>To start <code>rippled</code> in stand-alone mode with a new genesis ledger, use the <code>-a</code> and <code>--start</code> options:</li>
|
||||||
</ul>
|
</ul>
|
||||||
@@ -173,7 +173,7 @@
|
|||||||
</code></pre>
|
</code></pre>
|
||||||
<p><span class="draft-comment">(TODO: test this)</span></p>
|
<p><span class="draft-comment">(TODO: test this)</span></p>
|
||||||
<h3 id="6-manually-advance-the-ledger">6. Manually advance the ledger.</h3>
|
<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 need to <a href="#advancing-ledgers-in-stand-alone-mode">manually advance the ledger</a> to finalize it:</p>
|
<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
|
<pre><code>rippled ledger_accept --conf=/path/to/rippled.cfg
|
||||||
</code></pre>
|
</code></pre>
|
||||||
<h2 id="advancing-ledgers-in-stand-alone-mode">Advancing Ledgers in Stand-Alone Mode</h2>
|
<h2 id="advancing-ledgers-in-stand-alone-mode">Advancing Ledgers in Stand-Alone Mode</h2>
|
||||||
@@ -181,7 +181,7 @@
|
|||||||
<pre><code>rippled ledger_accept --conf=/path/to/rippled.cfg
|
<pre><code>rippled ledger_accept --conf=/path/to/rippled.cfg
|
||||||
</code></pre>
|
</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="https://ripple.com/knowledge_center/the-ripple-ledger-consensus-process/">The Ripple Ledger Consensus Process</a>.)</p>
|
<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="https://ripple.com/knowledge_center/the-ripple-ledger-consensus-process/">The Ripple 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 different <code>rippled</code> servers may see transactions in a different order.) When using <code>rippled</code> in stand-alone mode, it is important to manually advance the ledger before submitting a transaction that depends on the result of a previous transaction. Otherwise, the second transaction might be executed before the first transaction when you manually advance the ledger. <strong>Note:</strong> You can safely submit multiple transactions from a single account to a single ledger, because <code>rippled</code> sorts transactions from the same account in ascending order by <code>Sequence</code> number.</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 different <code>rippled</code> servers may see transactions in a 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 previous transaction. Otherwise, the second transaction might be executed before the first transaction when you manually advance the ledger. <strong>Note:</strong> You can safely submit multiple transactions from a single account to a single ledger, because <code>rippled</code> sorts transactions from the same account in ascending order by <code>Sequence</code> number.</p>
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ Many objects in the ledger are owned by a particular account, and therefore coun
|
|||||||
|
|
||||||
* [Offers](reference-ledger-format.html#offer) are owned by the account that placed them. An Offer can be automatically removed from the ledger if it is fully consumed or if it is found unfunded during transaction processing. Alternatively, the owner can cancel an offer by sending an [OfferCancel transaction](reference-transaction-format.html#offercancel), or by sending an [OfferCreate transaction](reference-transaction-format.html#offercreate) that contains an `OfferSequence` parameter.
|
* [Offers](reference-ledger-format.html#offer) are owned by the account that placed them. An Offer can be automatically removed from the ledger if it is fully consumed or if it is found unfunded during transaction processing. Alternatively, the owner can cancel an offer by sending an [OfferCancel transaction](reference-transaction-format.html#offercancel), or by sending an [OfferCreate transaction](reference-transaction-format.html#offercreate) that contains an `OfferSequence` parameter.
|
||||||
* [Trust lines](reference-ledger-format.html#ripplestate) are shared between two accounts. The owner reserve can apply to one or both of the accounts, depending on whether the fields that account controls are in their default state. See [Contributing to the Owner Reserve](reference-ledger-format.html#contributing-to-the-owner-reserve) for details.
|
* [Trust lines](reference-ledger-format.html#ripplestate) are shared between two accounts. The owner reserve can apply to one or both of the accounts, depending on whether the fields that account controls are in their default state. See [Contributing to the Owner Reserve](reference-ledger-format.html#contributing-to-the-owner-reserve) for details.
|
||||||
|
* A single [SignerList](reference-ledger-format.html#signerlist) counts as 3 to 10 objects for purposes of the owner reserve, depending on how many members it has. See also: [SignerLists and Reserves](reference-ledger-format.html#signerlists-and-reserves).
|
||||||
* [Owner directories](reference-ledger-format.html#directorynode) list all the ledger nodes that contribute to an account's owner reserve. However, the owner directory itself does not count towards the reserve.
|
* [Owner directories](reference-ledger-format.html#directorynode) list all the ledger nodes that contribute to an account's owner reserve. However, the owner directory itself does not count towards the reserve.
|
||||||
|
|
||||||
#### Owner Reserve Edge Cases ####
|
#### Owner Reserve Edge Cases ####
|
||||||
@@ -40,4 +41,3 @@ When an account has less XRP than its current reserve requirement, it cannot sen
|
|||||||
## Changing the Reserve Requirements ##
|
## Changing the Reserve Requirements ##
|
||||||
|
|
||||||
The Ripple Consensus Ledger has a mechanism for changing the reserve requirements in order to account for long-term changes in the value of XRP. Any changes have to be approved by the consensus process. See [Fee Voting](concept-fee-voting.html) for more information.
|
The Ripple Consensus Ledger has a mechanism for changing the reserve requirements in order to account for long-term changes in the value of XRP. Any changes have to be approved by the consensus process. See [Fee Voting](concept-fee-voting.html) for more information.
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
Stand-Alone Mode
|
Stand-Alone Mode
|
||||||
===============================================================================
|
===============================================================================
|
||||||
|
|
||||||
You can run `rippled` in stand-alone mode without a consensus of trusted servers. In stand-alone mode, `rippled` does not communicate with any other servers in the Ripple peer-to-peer network, but you can perform most of the same actions on your local server only. Stand-alone provides a method for testing `rippled` behavior, including the effects of [Amendments](concept-amendments.html) before those Amendments have gone into effect across the decentralized network.
|
You can run `rippled` in stand-alone mode without a consensus of trusted servers. In stand-alone mode, `rippled` does not communicate with any other servers in the Ripple 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 `rippled` behavior, including the effects of [Amendments](concept-amendments.html) before those Amendments have gone into effect across the decentralized network.
|
||||||
|
|
||||||
When you run `rippled` in stand-alone mode, you have to tell it what ledger version to start from:
|
When you run `rippled` in stand-alone mode, you have to tell it what ledger version to start from:
|
||||||
|
|
||||||
@@ -12,7 +12,7 @@ When you run `rippled` in stand-alone mode, you have to tell it what ledger vers
|
|||||||
|
|
||||||
New Genesis Ledger
|
New Genesis Ledger
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
In stand-alone mode, you can have `rippled` create a new genesis ledger. This provides a known state, with none of the ledger history from the production Ripple network. (This is very useful for unit tests, among other things.)
|
In stand-alone mode, you can have `rippled` create a new genesis ledger. This provides a known state, with none of the ledger history from the production Ripple Consensus Ledger. (This is very useful for unit tests, among other things.)
|
||||||
|
|
||||||
* To start `rippled` in stand-alone mode with a new genesis ledger, use the `-a` and `--start` options:
|
* To start `rippled` in stand-alone mode with a new genesis ledger, use the `-a` and `--start` options:
|
||||||
|
|
||||||
@@ -29,6 +29,7 @@ In a genesis ledger, the [genesis account](reference-rippled.html#special-addres
|
|||||||
**Caution:** If you create a new genesis ledger, the hard-coded default [Reserve](concept-reserves.html) is **200 XRP** minimum for an account, with an increment of **50 XRP** per object in the ledger. These values are higher than the current reserve requirements of the production network. (See also: [Fee Voting](concept-fee-voting.html))
|
**Caution:** If you create a new genesis ledger, the hard-coded default [Reserve](concept-reserves.html) is **200 XRP** minimum for an account, with an increment of **50 XRP** per object in the ledger. These values are higher than the current reserve requirements of the production network. (See also: [Fee Voting](concept-fee-voting.html))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Load Saved Ledger
|
Load Saved Ledger
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
You can start with a ledger version that was saved to disk if your `rippled` server was previously synced with the Ripple peer-to-peer network (either the production network or the [Test Net](tutorial-rippled-setup.html#parallel-networks)).
|
You can start with a ledger version that was saved to disk if your `rippled` server was previously synced with the Ripple peer-to-peer network (either the production network or the [Test Net](tutorial-rippled-setup.html#parallel-networks)).
|
||||||
@@ -75,7 +76,7 @@ rippled -a --ledger 19860944 --conf=/path/to/rippled.cfg
|
|||||||
|
|
||||||
### 6. Manually advance the ledger. ###
|
### 6. Manually advance the ledger. ###
|
||||||
|
|
||||||
When you load a ledger with `--ledger` in stand-alone mode, it goes to the current open ledger, so you need to [manually advance the ledger](#advancing-ledgers-in-stand-alone-mode) to finalize it:
|
When you load a ledger with `--ledger` in stand-alone mode, it goes to the current open ledger, so you must [manually advance the ledger](#advancing-ledgers-in-stand-alone-mode):
|
||||||
|
|
||||||
```
|
```
|
||||||
rippled ledger_accept --conf=/path/to/rippled.cfg
|
rippled ledger_accept --conf=/path/to/rippled.cfg
|
||||||
@@ -93,4 +94,4 @@ rippled ledger_accept --conf=/path/to/rippled.cfg
|
|||||||
|
|
||||||
In stand-alone mode, `rippled` makes no distinction between a "closed" ledger version and a "validated" ledger version. (For more information about the difference, see [The Ripple Ledger Consensus Process](https://ripple.com/knowledge_center/the-ripple-ledger-consensus-process/).)
|
In stand-alone mode, `rippled` makes no distinction between a "closed" ledger version and a "validated" ledger version. (For more information about the difference, see [The Ripple Ledger Consensus Process](https://ripple.com/knowledge_center/the-ripple-ledger-consensus-process/).)
|
||||||
|
|
||||||
Whenever `rippled` closes a ledger, it reorders the transactions according to a deterministic but hard-to-game algorithm. (This is an important part of consensus, since different `rippled` servers may see transactions in a different order.) When using `rippled` in stand-alone mode, it is important to manually advance the ledger before submitting a transaction that depends on the result of a previous transaction. Otherwise, the second transaction might be executed before the first transaction when you manually advance the ledger. **Note:** You can safely submit multiple transactions from a single account to a single ledger, because `rippled` sorts transactions from the same account in ascending order by `Sequence` number.
|
Whenever `rippled` closes a ledger, it reorders the transactions according to a deterministic but hard-to-game algorithm. (This is an important part of consensus, since different `rippled` servers may see transactions in a different order.) When using `rippled` in stand-alone mode, you should manually advance the ledger before submitting a transaction that depends on the result of a previous transaction. Otherwise, the second transaction might be executed before the first transaction when you manually advance the ledger. **Note:** You can safely submit multiple transactions from a single account to a single ledger, because `rippled` sorts transactions from the same account in ascending order by `Sequence` number.
|
||||||
|
|||||||
@@ -451,6 +451,8 @@ A SignerList node has the following fields:
|
|||||||
| PreviousTxnID | String | Hash256 | The identifying hash of the transaction that most recently modified this node. |
|
| PreviousTxnID | String | Hash256 | The identifying hash of the transaction that most recently modified this node. |
|
||||||
| PreviousTxnLgrSeq | Number | UInt32 | The sequence number (`ledger_index`) of the ledger that contains the transaction that most recently modified this node. |
|
| PreviousTxnLgrSeq | Number | UInt32 | The sequence number (`ledger_index`) of the ledger that contains the transaction that most recently modified this node. |
|
||||||
|
|
||||||
|
The `SignerEntries` may be any combination of funded and unfunded addresses that use either secp256k1 or ed25519 keys.
|
||||||
|
|
||||||
### SignerEntry object ###
|
### SignerEntry object ###
|
||||||
|
|
||||||
Each member of the `SignerEntries` field is an object that describes that signer in the list. A SignerEntry has the following fields:
|
Each member of the `SignerEntries` field is an object that describes that signer in the list. A SignerEntry has the following fields:
|
||||||
@@ -465,4 +467,3 @@ When processing a multi-signed transaction, the server dereferences the `Account
|
|||||||
### SignerLists and Reserves ###
|
### SignerLists and Reserves ###
|
||||||
|
|
||||||
A SignerList contributes to the [Account Reserve](https://wiki.ripple.com/Reserves). The SignerList itself counts as two objects, and each member of the list counts as one, so that the total owner reserve associated with a SignerList is anywhere from 3 times to 10 times the reserve required by a single trust line ([RippleState](#ripplestate)) or [Offer](#offer) node in the ledger.
|
A SignerList contributes to the [Account Reserve](https://wiki.ripple.com/Reserves). The SignerList itself counts as two objects, and each member of the list counts as one, so that the total owner reserve associated with a SignerList is anywhere from 3 times to 10 times the reserve required by a single trust line ([RippleState](#ripplestate)) or [Offer](#offer) node in the ledger.
|
||||||
|
|
||||||
|
|||||||
@@ -6296,6 +6296,12 @@ __*Caution:*__ If this command results in an error messages, the message can con
|
|||||||
* `noPath` - The transaction did not include paths, and the server was unable to find a path by which this payment can occur.
|
* `noPath` - The transaction did not include paths, and the server was unable to find a path by which this payment can occur.
|
||||||
|
|
||||||
|
|
||||||
|
## sign_for ##
|
||||||
|
|
||||||
|
The `sign_for` command provides one signature for a multi-signed transaction. takes an address and related secret, and a transaction in JSON form. (TODO: finish this section.) It generates a signature for that transaction, using the secret key and address specified. By using this, you can provide signatures that contribute to a multi-signed transaction. (The signatures should come from the members of your SignerList.)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## submit ##
|
## submit ##
|
||||||
[[Source]<br>](https://github.com/ripple/rippled/blob/master/src/ripple/rpc/handlers/Submit.cpp "Source")
|
[[Source]<br>](https://github.com/ripple/rippled/blob/master/src/ripple/rpc/handlers/Submit.cpp "Source")
|
||||||
|
|
||||||
@@ -6526,6 +6532,12 @@ __*Caution:*__ If this command results in an error messages, the message can con
|
|||||||
* `internalJson` - An internal error occurred when serializing the transaction to JSON. This could be caused by many aspects of the transaction, including a bad signature or some fields being malformed.
|
* `internalJson` - An internal error occurred when serializing the transaction to JSON. This could be caused by many aspects of the transaction, including a bad signature or some fields being malformed.
|
||||||
|
|
||||||
|
|
||||||
|
## submit_multisigned ##
|
||||||
|
|
||||||
|
The `submit_multisigned` command takes a transaction specification with multiple signatures and applies that transaction. (TODO: finish this section.)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## book_offers ##
|
## book_offers ##
|
||||||
[[Source]<br>](https://github.com/ripple/rippled/blob/develop/src/ripple/rpc/handlers/BookOffers.cpp "Source")
|
[[Source]<br>](https://github.com/ripple/rippled/blob/develop/src/ripple/rpc/handlers/BookOffers.cpp "Source")
|
||||||
|
|
||||||
|
|||||||
@@ -19,18 +19,39 @@ Additionally, there are *Psuedo-Transactions* that are not created and submitted
|
|||||||
|
|
||||||
Transactions are only valid if signed, submitted, and accepted into a validated ledger version. There are many ways a transaction can fail.
|
Transactions are only valid if signed, submitted, and accepted into a validated ledger version. There are many ways a transaction can fail.
|
||||||
|
|
||||||
* [Signing and Sending Transactions](#signing-and-sending-transactions)
|
* [Authorized Transactions](#authorizing-transactions)
|
||||||
* [Reliable Transaction Submission](#reliable-transaction-submission)
|
* [Reliable Transaction Submission](#reliable-transaction-submission)
|
||||||
* [Transaction Results - How to find and interpret transaction results](#transaction-results)
|
* [Transaction Results - How to find and interpret transaction results](#transaction-results)
|
||||||
* [Full Transaction Response List - Complete table of all error codes](#full-transaction-response-list)
|
* [Full Transaction Response List - Complete table of all error codes](#full-transaction-response-list)
|
||||||
|
|
||||||
## Signing and Sending Transactions ##
|
## Authorizing Transactions ##
|
||||||
|
|
||||||
Signing a transaction cryptographically proves that the person in charge of the account sending the transaction is authorized to do so. Only signed transactions can be submitted to the network and included in a validated ledger. A signed transaction is immutable: its contents cannot change, and the signature is not valid for any other transaction.
|
In the decentralized Ripple Consensus Ledger, a digital signature proves that a transaction is authorized to perform a specific set of actions. Only signed transactions can be submitted to the network and included in a validated ledger. A signed transaction is immutable: its contents cannot change, and the signature is not valid for any other transaction.
|
||||||
|
|
||||||
You sign a transaction using a secret key: either the master secret, or a regular secret if the account has a regular key pair associated with it. (See [SetRegularKey](#setregularkey) for details.) If your account has a SignerList associated with it, you can use a [multi-signature](#multi-signing) instead.
|
A transaction can be authorized by any of the following types of signatures:
|
||||||
|
|
||||||
Typically, you create a transaction in JSON format first. Here is an example of an unsigned Payment-type transaction in JSON:
|
* A single signature from the master secret key that is mathematically associated with the address. You can disable or enable the master key using an [AccountSet transaction](#accountset).
|
||||||
|
* A single signature that matches a regular key enabled for the address. You can enable, remove, or replace a regular key using a [SetRegularKey transaction](#setregularkey).
|
||||||
|
* A [multi-signature](#multi-signing) that matches a list of signers enabled for the address. You can enable, remove, or replace a list of signers using a [SignerListSet transaction](#SignerListSet).
|
||||||
|
|
||||||
|
Any signature type can authorize any type of transaction, with the following exceptions:
|
||||||
|
|
||||||
|
* Only the master key can [disable the master key](#accountset-flags).
|
||||||
|
* Only the master key can [permanently give up the ability to freeze](concept-freeze.html#no-freeze).
|
||||||
|
* You can never remove the last method of signing transactions from an address.
|
||||||
|
|
||||||
|
## Signing and Submitting Transactions ##
|
||||||
|
|
||||||
|
Sending a transaction to the Ripple Consensus Ledger involves several steps:
|
||||||
|
|
||||||
|
1. Create an unsigned transaction in JSON format.
|
||||||
|
2. Use one or more signatures to [authorize the transaction](#authorizing-transactions).
|
||||||
|
3. Submit a transaction to a `rippled` server. If the transaction is properly formed, the server provisionally applies the transaction to its current version of the ledger and relays the transaction to other members of the peer-to-peer network.
|
||||||
|
4. The [consensus process](https://ripple.com/knowledge_center/the-ripple-ledger-consensus-process/) determines which provisional transactions get included in the next validated ledger.
|
||||||
|
5. The `rippled` servers apply those transactions to the previous ledger in a canonical order and share their results.
|
||||||
|
6. If enough [trusted validators](tutorial-rippled-setup.html#reasons-to-run-a-validator) created the exact same ledger, that ledger is declared _validated_ and the [results of the transactions](#transaction-results) in that ledger are immutable.
|
||||||
|
|
||||||
|
Here is an example of an unsigned [Payment-type transaction](#payment) in JSON:
|
||||||
|
|
||||||
```
|
```
|
||||||
{
|
{
|
||||||
@@ -155,31 +176,14 @@ After a transaction has been submitted, if it gets accepted into a validated led
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
### Multi-Signing ###
|
### Multi-Signing ###
|
||||||
|
|
||||||
Multi-signing in Ripple is the act of authorizing transactions for the Ripple
|
Multi-signing in Ripple is the act of [authorizing transactions](#authorizing-transactions) for the Ripple Consensus Ledger by using a combination of multiple secret keys. Multi-signing is due to be enabled by an [Amendment](concept-amendments.html) to the Ripple Consensus Protocol. You can use multi-signing in addition to, or instead of, a master key, a [regular key](#setregularkey), or both.
|
||||||
Consensus Ledger by using a combination of multiple secret keys. Multi-signing
|
|
||||||
allows various use cases including:
|
|
||||||
|
|
||||||
* If you require keys from different devices, a malicious user must compromise multiple machines in order to send transactions on your behalf.
|
The [SignerListSet transaction](#signerlistset) defines which addresses can authorize transactions from your address. You can include up to 8 addresses in a SignerList. You can achieve several different configurations using the weight and quorum values of the signer list.
|
||||||
* If the keys to an account are in the custody of entirely different people, those people must collaborate in order to send transaction from that account.
|
|
||||||
* Delegate a group of others who can send transactions for you if you are unavailable or unable to sign normally.
|
|
||||||
* ... and more.
|
|
||||||
|
|
||||||
To set up multi-signing for an account, the process is straightforward:
|
|
||||||
|
|
||||||
1. Use a [SignerListSet transaction](#signerlistset) to define which accounts or keys can, together, authorize transactions for this account.
|
|
||||||
2. Optionally disable the master key with an [AccountSet transaction](#accountset) using the `asfDisableMaster` flag.
|
|
||||||
3. Optionally remove the existing regular key (if any) with a [SetRegularKey transaction](#setregularkey).
|
|
||||||
|
|
||||||
After an account has a SignerList associated with it, the process of submitting a multi-signed transaction is as follows:
|
|
||||||
|
|
||||||
1. Create the transaction to be signed as a JSON object
|
|
||||||
2. Generate a signature for each account using the [`sign_for` command](rippled-apis.html#sign-for).
|
|
||||||
3. Combine the signatures and submit using the [`submit_multisigned` command](rippled-apis.html#submit-multisigned).
|
|
||||||
|
|
||||||
Main article: [How to Multi-Sign](multisign.html)
|
|
||||||
|
|
||||||
|
For more information, see [How to Multi-Sign](tutorial-multisign.html).
|
||||||
|
|
||||||
|
|
||||||
### Reliable Transaction Submission ###
|
### Reliable Transaction Submission ###
|
||||||
@@ -550,7 +554,7 @@ In rippled's WebSocket and JSON-RPC APIs, the TransferRate is represented as an
|
|||||||
|
|
||||||
[[Source]<br>](https://github.com/ripple/rippled/blob/4239880acb5e559446d2067f00dabb31cf102a23/src/ripple/app/transactors/SetRegularKey.cpp "Source")
|
[[Source]<br>](https://github.com/ripple/rippled/blob/4239880acb5e559446d2067f00dabb31cf102a23/src/ripple/app/transactors/SetRegularKey.cpp "Source")
|
||||||
|
|
||||||
A SetRegularKey transaction changes the regular key used by the account to sign future transactions.
|
A SetRegularKey transaction changes the regular key associated with an address.
|
||||||
|
|
||||||
```
|
```
|
||||||
{
|
{
|
||||||
@@ -564,13 +568,15 @@ A SetRegularKey transaction changes the regular key used by the account to sign
|
|||||||
|
|
||||||
| Field | JSON Type | [Internal Type](https://wiki.ripple.com/Binary_Format) | Description |
|
| Field | JSON Type | [Internal Type](https://wiki.ripple.com/Binary_Format) | Description |
|
||||||
|-------|-----------|--------------------------------------------------------|-------------|
|
|-------|-----------|--------------------------------------------------------|-------------|
|
||||||
| RegularKey | String | Account | (Optional) The public key of a new keypair, to use as the regular key to this account, as a base-58-encoded string in the same format as an account address. If omitted, removes the existing regular key. |
|
| RegularKey | String | AccountID | (Optional) A base-58-encoded [Ripple address](reference-rippled.html#addresses) to use as the regular key. If omitted, removes the existing regular key. |
|
||||||
|
|
||||||
Instead of using an account's master key to sign transactions, you can set an alternate key pair, called the "Regular Key". As long as the public key for this key pair is set in the `RegularKey` field of an account this way, then the secret of the Regular Key pair can be used to sign transactions. (Other methods of signing transactions can also be used, including [multi-signing](#multi-signing) or the master key.
|
In addition to the master key, which is mathematically-related to an address, you can associate **at most 1 additional key pair** with an address using this type of transaction. The additional key pair is called a _regular key_. If your address has a regular key pair defined, you can use the secret key of the regular key pair to [authorize transactions](#authorizing-transactions).
|
||||||
|
|
||||||
A Regular Key pair is generated in the same way as any other Ripple keys (for example, with [wallet_propose](rippled-apis.html#wallet-propose)), but it can be changed. A Master Key pair is an intrinsic part of the account's identity (the address is derived from the master public key). The Master Key can be [disabled](#accountset-flags) but it cannot be changed. Therefore, it is beneficial to security sign transactions with a Regular Key instead of the master key whenever possible. For even greater security, you can use [multi-signing](#multi-signing), but multi-signing costs additional XRP in transaction fees and reserves.
|
A regular key pair is generated in the same way as any other Ripple keys (for example, with [wallet_propose](reference-rippled.html#wallet-propose)), but it can be changed. A master key pair is an intrinsic part of an address's identity (the address is derived from the master public key). You can [disable](#accountset-flags) a master key but you cannot change it.
|
||||||
|
|
||||||
If your regular key is compromised, but the master key is not, you can use a SetRegularKey transaction to regain control of your account. In some cases, you can even send a [key reset transaction](concept-transaction-cost.html#key-reset-transaction) without paying the [transaction cost](#transaction-cost).
|
You can protect your master secret by using a regular key instead of the master key to sign transactions where possible. If your regular key is compromised, but the master key is not, you can use a SetRegularKey transaction to regain control of your address. In some cases, you can even send a [key reset transaction](concept-transaction-cost.html#key-reset-transaction) without paying the [transaction cost](#transaction-cost).
|
||||||
|
|
||||||
|
For even greater security, you can use [multi-signing](#multi-signing), but multi-signing requires additional XRP for the [transaction cost](concept-transaction-cost.html) and [reserve](concept-reserves.html).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -778,7 +784,7 @@ Transactions of the TrustSet type support additional values in the [`Flags` fiel
|
|||||||
## SignerListSet ##
|
## SignerListSet ##
|
||||||
[[Source]<br>](https://github.com/ripple/rippled/blob/ef511282709a6a0721b504c6b7703f9de3eecf38/src/ripple/app/tx/impl/SetSignerList.cpp "Source")
|
[[Source]<br>](https://github.com/ripple/rippled/blob/ef511282709a6a0721b504c6b7703f9de3eecf38/src/ripple/app/tx/impl/SetSignerList.cpp "Source")
|
||||||
|
|
||||||
The SignerListSet transaction creates, modifies, or removes a list of signers that can be used to multi-sign a transaction.
|
The SignerListSet transaction creates, modifies, or removes a list of signers that can be used to [multi-sign](#multi-signing) a transaction.
|
||||||
|
|
||||||
Example SignerListSet:
|
Example SignerListSet:
|
||||||
|
|
||||||
@@ -815,14 +821,15 @@ Example SignerListSet:
|
|||||||
| Field | JSON Type | [Internal Type](https://wiki.ripple.com/Binary_Format) | Description |
|
| Field | JSON Type | [Internal Type](https://wiki.ripple.com/Binary_Format) | Description |
|
||||||
|-------|-----------|--------------------------------------------------------|-------------|
|
|-------|-----------|--------------------------------------------------------|-------------|
|
||||||
| SignerQuorum | Number | UInt32 | A target number for the signer weights. A multi-signature from this list is valid only if the sum weights of the signatures provided is equal or greater than this value. To delete a SignerList, use the value `0`. |
|
| SignerQuorum | Number | UInt32 | A target number for the signer weights. A multi-signature from this list is valid only if the sum weights of the signatures provided is equal or greater than this value. To delete a SignerList, use the value `0`. |
|
||||||
| SignerEntries | Array | Array | (Omitted when deleting) Array of [SignerEntry objects](ripple-ledger.html#signerentry-object), indicating the addresses and weights of signers in this list. A SignerList must have at least 1 member and no more than 8 members. No address may appear more than once in the list, nor may the `Account` submitting the transaction appear in the list. |
|
| SignerEntries | Array | Array | (Omitted when deleting) Array of [SignerEntry objects](reference-ledger-format.html#signerentry-object), indicating the addresses and weights of signers in this list. A SignerList must have at least 1 member and no more than 8 members. No address may appear more than once in the list, nor may the `Account` submitting the transaction appear in the list. |
|
||||||
|
|
||||||
An account may not have more than one SignerList. A successful SignerListSet transaction replaces the existing SignerList, if one exists. To delete a SignerList, you must set `SignerQuorum` to `0` _and_ omit the `SignerEntries` field. Otherwise, the transaction fails with the error [temMALFORMED](#tem-codes). A transaction to delete a SignerList is considered successful even if there was no SignerList to delete.
|
An account may not have more than one SignerList. A successful SignerListSet transaction replaces the existing SignerList, if one exists. To delete a SignerList, you must set `SignerQuorum` to `0` _and_ omit the `SignerEntries` field. Otherwise, the transaction fails with the error [temMALFORMED](#tem-codes). A transaction to delete a SignerList is considered successful even if there was no SignerList to delete.
|
||||||
|
|
||||||
You cannot create a SignerList such that the SignerQuorum could never be met. The SignerQuorum must be greater than 0 but less than or equal to the sum of the `SignerWeight` values in the list. Otherwise, the transaction fails with the error [temMALFORMED](#tem-codes).
|
You cannot create a SignerList such that the SignerQuorum could never be met. The SignerQuorum must be greater than 0 but less than or equal to the sum of the `SignerWeight` values in the list. Otherwise, the transaction fails with the error [temMALFORMED](#tem-codes).
|
||||||
|
|
||||||
You cannot remove the last method of signing transactions from an account. If an account's master key is disabled (it has the [`lsfDisableMaster` flag](ripple-ledger.html#accountroot-flags) enabled) and the account does not have a Regular Key configured, then you cannot delete the SignerList from the account. Instead, the transaction fails with the error [tecNO\_ALTERNATIVE\_KEY](#tec-codes).
|
You can create, update, or remove a SignerList using the master key, regular key, or the current SignerList, if those methods of signing transactions are available.
|
||||||
|
|
||||||
|
You cannot remove the last method of signing transactions from an account. If an account's master key is disabled (it has the [`lsfDisableMaster` flag](ripple-ledger.html#accountroot-flags) enabled) and the account does not have a [Regular Key](#setregularkey) configured, then you cannot delete the SignerList from the account. Instead, the transaction fails with the error [tecNO\_ALTERNATIVE\_KEY](#tec-codes).
|
||||||
|
|
||||||
|
|
||||||
# Pseudo-Transactions #
|
# Pseudo-Transactions #
|
||||||
|
|||||||
@@ -1,117 +1,81 @@
|
|||||||
Introduction to Multi-Signing
|
How to Multi-Sign
|
||||||
===============================================================================
|
=============================
|
||||||
|
|
||||||
Multi-signing in Ripple is the act of authorizing transactions for the Ripple Consensus Ledger by using a combination of multiple secret keys. After setting up multi-signing for an account, you can put the master secret in cold storage, or even disable the master key entirely. With multiple secret keys required to authorize a multi-signature, you can improve security in several ways.
|
Multi-signing is one of three ways to authorize transactions for the Ripple Consensus Ledger, alongside signing with [regular keys](reference-transaction-format.html#setregularkey) and master keys. You can configure your address to allow any combination of the three methods to authorize transactions.
|
||||||
|
|
||||||
* If you keep an account's keys on different devices, a malicious user must compromise multiple machines in order to send transactions on your behalf.
|
Benefits of multi-signing include:
|
||||||
* If the keys to an account are in the custody of entirely different people, those people must collaborate in order to send transaction from that account.
|
|
||||||
* You can use the SignerList as a backup, to delegate a group of others who can send transactions for you if you are unavailable or unable to sign using your regular key.
|
* You can require keys from different devices, so that a malicious actor must compromise multiple machines to send transactions on your behalf.
|
||||||
* Even more uses than can be described here.
|
* You can share custody of an address between multiple people, each of whom only has one of several keys necessary to send transactions from that address.
|
||||||
|
* You can delegate the power to send transactions from your address to a group of people, who can control your address if you are unavailable or unable to sign normally.
|
||||||
|
* ... and more.
|
||||||
|
|
||||||
|
To use multi-signing:
|
||||||
|
|
||||||
|
1. [The Ripple peer-to-peer network must have multi-signing enabled.](#availability-of-multi-signing)
|
||||||
|
2. [Set up a list of signers on your account.](#setting-up-multi-sign)
|
||||||
|
3. [Send transactions using multiple signatures.](#sending-a-multi-signed-transaction)
|
||||||
|
|
||||||
|
|
||||||
Availability of Multi-Signing
|
Availability of Multi-Signing
|
||||||
-------------------------------------------------------------------------------
|
-----------------------------
|
||||||
|
|
||||||
Multi-signing is built into `rippled` starting with version **0.31.0**. Because multi-signing is a change in transaction processing, the change is due to be enabled by an **Amendment** to the Ripple Consensus Protocol. This Amendment must be approved by a consensus of validators showing consistent support for the feature over a period of time. For more information, see [Amendments](concept-amendments.html).
|
Multi-signing is built into `rippled` starting with version **0.31.0**. Because multi-signing is a change in transaction processing, the change is due to be enabled by an **Amendment** to the Ripple Consensus Protocol. This Amendment must be approved by a consensus of validators showing consistent support for the feature over a period of time. For more information, see [Amendments](concept-amendments.html).
|
||||||
|
|
||||||
You can test multi-signing by running `rippled` in [stand-alone mode](concept-stand-alone-mode.html) with the Multi-Sign feature enabled. To enable Multi-Sign for testing, add the following stanza to your `rippled.cfg`:
|
If you want to test multi-signing before it becomes available in the production network, or without risking real money, you can do so by running `rippled` in [stand-alone mode](concept-stand-alone-mode.html) with the MultiSign feature enabled. To enable multi-signing for testing, add the following stanza to your `rippled.cfg`:
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
MultiSign
|
MultiSign
|
||||||
|
|
||||||
|
|
||||||
How to Multi-Sign
|
Setting up Multi-Signing
|
||||||
===============================================================================
|
------------------------
|
||||||
|
|
||||||
The basic process of Multi-Signing a transaction is necessarily more complex than the process of signing a transaction with a single master key or regular key.
|
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 Ripple Consensus Ledger as a [SignerList node](reference-ledger-format.html#signerlist). The following procedure demonstrates how to set up a SignerList for your address:
|
||||||
|
|
||||||
## 1. (Optional) Generate keys for a new wallet ##
|
|
||||||
|
|
||||||
This step is not strictly necessary. For this process, we generate and fund a new Ripple account and then set up multi-signing for that account. To set up multi-signing on an existing Ripple account, skip ahead to [Step 4: creating a signer list](4-create-a-signerlist-on-the-new-account-with-a-signerlistset-transaction).
|
### 1. Prepare a funded address ###
|
||||||
|
|
||||||
|
You need a Ripple address that can send transactions, and has enough XRP available. Multi-signing requires more than the usual amount of XRP for the [account reserve](concept-reserves.html) and [transaction cost](concept-transaction-cost.html), increasing with the number of signers and signatures you use.
|
||||||
|
|
||||||
|
If you started `rippled` in [stand-alone mode](concept-stand-alone-mode.html) with a new genesis ledger, you must:
|
||||||
|
|
||||||
|
1. Generate keys for a new address, or reuse keys you already have.
|
||||||
|
2. Submit a Payment transaction to fund the new address from the genesis account. (Send at least 100,000,000 [drops of XRP](reference-rippled.html#specifying-currency-amounts).)
|
||||||
|
3. Manually close the ledger.
|
||||||
|
|
||||||
|
|
||||||
|
### 2. Prepare member keys ###
|
||||||
|
|
||||||
|
You need several sets of Ripple 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 [`wallet_propose` command](reference-rippled.html#wallet-propose). For example:
|
||||||
|
|
||||||
$ rippled wallet_propose
|
$ rippled wallet_propose
|
||||||
Loading: "/home/mduo13/.config/ripple/rippled.cfg"
|
Loading: "/home/mduo13/.config/ripple/rippled.cfg"
|
||||||
Connecting to 127.0.0.1:5005
|
Connecting to 127.0.0.1:5005
|
||||||
{
|
{
|
||||||
"result" : {
|
"result" : {
|
||||||
"account_id" : "rEuLyBCvcw4CFmzv8RepSiAoNgF8tTGJQC",
|
"account_id" : "rnRJ4dpSBKDR2M1itf4Ah6tZZm5xuNZFPH",
|
||||||
"key_type" : "secp256k1",
|
"key_type" : "secp256k1",
|
||||||
"master_key" : "LOST FOUR ALOE ABE SLUG ITS HACK MAGI SOCK BASS APE DELL",
|
"master_key" : "FLOG SEND GOES CUFF GAGE FAT ANTI DEL GUM TIRE ISLE BEAR",
|
||||||
"master_seed" : "sn1CmMEkPijNrfyr8HJqsgP416dr3",
|
"master_seed" : "snheH5UUjU4CWqiNVLny2k21TyKPC",
|
||||||
"master_seed_hex" : "E42AD02985BB56923DFC1D002DB510B3",
|
"master_seed_hex" : "A9F859765EB8614D26809836382AFB82",
|
||||||
"public_key" : "aBQgQDutj8YUc7ZRtfj86dnzPCvPcRHtUszxeCCDMgZ7Zq1Thfri",
|
"public_key" : "aBR4hxFXcDNHnGYvTiqb2KU8TTTV1cYV9wXTAuz2DjBm7S8TYEBU",
|
||||||
"public_key_hex" : "03668837C3DCA0F4858587703524E61BB40128B9F6910B80B4655E152CAEE2E321",
|
"public_key_hex" : "03C09A5D112B393D531E4F092E3A5769A5752129F0A9C55C61B3A226BB9B567B9B",
|
||||||
"status" : "success"
|
"status" : "success"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Take note of the `account_id` (Ripple Address) and `master_seed` (Ripple secret key) for each one you generate.
|
||||||
As always, be sure that an account's secret key never gets transmitted to anyone you don't trust with full control of that account, and certainly not unencrypted over the network.
|
|
||||||
|
|
||||||
|
|
||||||
## 2. Fund the new account with an existing wallet ##
|
### 3. Send SignerListSet transaction ###
|
||||||
|
|
||||||
Again, this step is only necessary if you are setting up a new account to use multi-signing for this example.
|
[Sign and submit](reference-transaction-format.html#signing-and-submitting-transactions) a [SignerListSet transaction](reference-transaction-format.html#signerlistset) in the normal (single-signature) way. This associates a SignerList with your Ripple address, so that a combination of signatures from the members of that SignerList can multi-sign later transactions on your behalf.
|
||||||
|
|
||||||
$ rippled submit snoPBrXtMeMyMHUVTgbuqAfg1SUTb '{
|
|
||||||
> "TransactionType": "Payment",
|
|
||||||
> "Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
|
|
||||||
> "Destination": "rEuLyBCvcw4CFmzv8RepSiAoNgF8tTGJQC",
|
|
||||||
> "Amount": "100000000",
|
|
||||||
> "Flags": 2147483648
|
|
||||||
> }'
|
|
||||||
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" : "12000022800000002400000004614000000005F5E10068400000000000000A73210330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD02074473045022100ED13CDD4B8F6BA836F7732A029316393A5D9B50712FE79972236ECAD850F813802203148D8944B0BF3D30A3177EFCE6A9F12B3F5A3C3AFF7B73E9A7D65B370E526EE8114B5F762798A53D543A014CAF8B297CFF8F2F937E88314A3780F5CB5A44D366520FC44055E8ED44D9A2270",
|
|
||||||
"tx_json" : {
|
|
||||||
"Account" : "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
|
|
||||||
"Amount" : "100000000",
|
|
||||||
"Destination" : "rEuLyBCvcw4CFmzv8RepSiAoNgF8tTGJQC",
|
|
||||||
"Fee" : "10",
|
|
||||||
"Flags" : 2147483648,
|
|
||||||
"Sequence" : 4,
|
|
||||||
"SigningPubKey" : "0330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD020",
|
|
||||||
"TransactionType" : "Payment",
|
|
||||||
"TxnSignature" : "3045022100ED13CDD4B8F6BA836F7732A029316393A5D9B50712FE79972236ECAD850F813802203148D8944B0BF3D30A3177EFCE6A9F12B3F5A3C3AFF7B73E9A7D65B370E526EE",
|
|
||||||
"hash" : "64FAA44F671E2CBB4E1E4156FCDA72BA3C32EF951C94EDDFEBEBE8BEC3F55696"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Make sure that the `engine_result` value in the response is **tesSUCCESS**. Otherwise, the transaction failed.
|
|
||||||
|
|
||||||
## 3. Close the ledger ##
|
|
||||||
|
|
||||||
If you are using the live network, you can wait for the ledger to close automatically as the result of consensus. This typically takes 4-7 seconds.
|
|
||||||
|
|
||||||
If you are running `rippled` in stand-alone mode, you must manually close the ledger with the [`ledger_accept` command](reference-rippled.html#ledger-accept).
|
|
||||||
|
|
||||||
$ rippled ledger_accept
|
|
||||||
Loading: "/home/mduo13/.config/ripple/rippled.cfg"
|
|
||||||
Connecting to 127.0.0.1:5005
|
|
||||||
{
|
|
||||||
"result" : {
|
|
||||||
"ledger_current_index" : 16061437,
|
|
||||||
"status" : "success"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
## 4. Create a SignerList on the new account with a SignerListSet transaction ##
|
|
||||||
|
|
||||||
Before you can multi-sign transactions, you must associate a SignerList with your account, so that RCL knows which keys can be used to sign for you. You do this with a [SignerListSet transaction](reference-transaction-format.html#signerlistset).
|
|
||||||
|
|
||||||
The `Account` values in your SignerList can be the addresses of funded accounts that exist in the ledger, or you can generate new addresses that are not currently in use. For funded accounts in the SignerList, a regular key associated with the account can contribute to a multi-signature, and the master key secret can be used only if it is not disabled. For unfunded addresses, only the master key associated with that address can be used to contribute to a multi-signature.
|
|
||||||
|
|
||||||
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.
|
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.
|
||||||
|
|
||||||
|
**Caution:** Never submit a secret key to a server you do not control. Do not transmit a secret key unencrypted over the network.
|
||||||
|
|
||||||
$ rippled submit shqZZy2Rzs9ZqWTCQAdqc3bKgxnYq '{
|
$ rippled submit shqZZy2Rzs9ZqWTCQAdqc3bKgxnYq '{
|
||||||
> "Flags": 0,
|
> "Flags": 0,
|
||||||
> "TransactionType": "SignerListSet",
|
> "TransactionType": "SignerListSet",
|
||||||
@@ -182,13 +146,16 @@ In this example, the SignerList has 3 members, with the weights and quorum set u
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Make sure that the `engine_result` value in the response is **tesSUCCESS**. Otherwise, the transaction failed.
|
Make sure that the [Transaction Result](reference-transaction-format.html#transaction-results) is [**tesSUCCESS**](reference-transaction-format.html#tes-success). Otherwise, the transaction failed.
|
||||||
|
|
||||||
## 5. Close the ledger again ##
|
**Note:** The more members in the SignerList, the more XRP your address must have for purposes of the [owner reserve](concept-reserves.html#owner-reserves). If your address does not have enough XRP, the transaction fails with [tecINSUFFICIENT_RESERVE](reference-transaction-format.html#tec-codes). See also: [SignerLists and Reserves](reference-ledger-format.html#signerlists-and-reserves).
|
||||||
|
|
||||||
As before, on the live network, you can wait for the ledger to close automatically.
|
|
||||||
|
|
||||||
If running `rippled` in stand-alone mode, use the [`ledger_accept` command](reference-rippled.html#ledger-accept) to manually close the ledger:
|
### 4. Close the ledger ###
|
||||||
|
|
||||||
|
On the live network, you can wait 4-7 seconds for the ledger to close automatically.
|
||||||
|
|
||||||
|
If you're running `rippled` in stand-alone mode, use the [`ledger_accept` command](reference-rippled.html#ledger-accept) to manually close the ledger:
|
||||||
|
|
||||||
$ rippled ledger_accept
|
$ rippled ledger_accept
|
||||||
Loading: "/home/mduo13/.config/ripple/rippled.cfg"
|
Loading: "/home/mduo13/.config/ripple/rippled.cfg"
|
||||||
@@ -201,9 +168,11 @@ If running `rippled` in stand-alone mode, use the [`ledger_accept` command](refe
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
## 6. Confirm the presence of the new signer list using account_objects ##
|
### 5. Confirm the new signer list ###
|
||||||
|
|
||||||
Normally an account can own many objects of different types (such as trust lines and offers). For this tutorial, we created a new account, so the SignerList is the only object in the response from the [`account_objects` command](reference-rippled.html#account-objects).
|
Use the [`account_objects` command](reference-rippled.html#account-objects) to confirm that the SignerList is associated with the address in the latest validated ledger.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
$ rippled account_objects rEuLyBCvcw4CFmzv8RepSiAoNgF8tTGJQC validated
|
$ rippled account_objects rEuLyBCvcw4CFmzv8RepSiAoNgF8tTGJQC validated
|
||||||
Loading: "/home/mduo13/.config/ripple/rippled.cfg"
|
Loading: "/home/mduo13/.config/ripple/rippled.cfg"
|
||||||
@@ -241,30 +210,6 @@ Normally an account can own many objects of different types (such as trust lines
|
|||||||
"SignerListID" : 0,
|
"SignerListID" : 0,
|
||||||
"SignerQuorum" : 3,
|
"SignerQuorum" : 3,
|
||||||
"index" : "79FD203E4DDDF2EA78B798C963487120C048C78652A28682425E47C96D016F92"
|
"index" : "79FD203E4DDDF2EA78B798C963487120C048C78652A28682425E47C96D016F92"
|
||||||
},
|
|
||||||
{
|
|
||||||
"Balance" : {
|
|
||||||
"currency" : "USD",
|
|
||||||
"issuer" : "rrrrrrrrrrrrrrrrrrrrBZbvji",
|
|
||||||
"value" : "0"
|
|
||||||
},
|
|
||||||
"Flags" : 2162688,
|
|
||||||
"HighLimit" : {
|
|
||||||
"currency" : "USD",
|
|
||||||
"issuer" : "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
|
|
||||||
"value" : "0"
|
|
||||||
},
|
|
||||||
"HighNode" : "0000000000000000",
|
|
||||||
"LedgerEntryType" : "RippleState",
|
|
||||||
"LowLimit" : {
|
|
||||||
"currency" : "USD",
|
|
||||||
"issuer" : "rEuLyBCvcw4CFmzv8RepSiAoNgF8tTGJQC",
|
|
||||||
"value" : "100"
|
|
||||||
},
|
|
||||||
"LowNode" : "0000000000000000",
|
|
||||||
"PreviousTxnID" : "BD636194C48FD7A100DE4C972336534C8E710FD008C0F3CF7BC5BF34DAF3C3E6",
|
|
||||||
"PreviousTxnLgrSeq" : 6,
|
|
||||||
"index" : "93E317B32022977C77810A2C558FBB28E30E744C68E73720622B797F957EC5FA"
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"ledger_hash" : "56E81069F06492FB410A70218C08169BE3AB3CFD5AEA20E999662D81DC361D9F",
|
"ledger_hash" : "56E81069F06492FB410A70218C08169BE3AB3CFD5AEA20E999662D81DC361D9F",
|
||||||
@@ -274,45 +219,65 @@ Normally an account can own many objects of different types (such as trust lines
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
If the SignerList is present with the expected contents, then your address is ready to multi-sign.
|
||||||
|
|
||||||
|
### 6. Further steps ###
|
||||||
|
|
||||||
|
At this point, your address is ready to [send a multi-signed transaction](#sending-a-multi-signed-transaction). You may also want to:
|
||||||
|
|
||||||
|
* Disable the address's master key by sending an [AccountSet transaction](reference-transaction-format.html#accountset) using the `asfDisableMaster` flag.
|
||||||
|
* Remove the address's regular key (if you previously set one) by sending a [SetRegularKey transaction](reference-transaction-format.html#setregularkey).
|
||||||
|
|
||||||
|
|
||||||
## 7. Create a new transaction that you plan to multi-sign ##
|
Sending a Multi-Signed Transaction
|
||||||
|
----------------------------------
|
||||||
|
|
||||||
You have to specify _everything_ about this transaction, including `Fee` and
|
Before you can multi-sign a transaction, first check that [multi-sign is available](#availability-of-multi-signing) and [set up multi-signing](#set-up-multi-sign) for your address. The following procedure demonstrates how to create, sign, and submit a multi-signed transaction.
|
||||||
`Sequence`. Also include the field `SigningPubKey` as an empty string -- this
|
|
||||||
indicates that the transaction is multi-signed.
|
|
||||||
|
|
||||||
Here's an example transaction we can send from our test account:
|
### 1. Create the transaction ##
|
||||||
|
|
||||||
|
Create a JSON object that represents the transaction you want to submit. You have to specify _everything_ about this transaction, including `Fee` and `Sequence`. Also include the field `SigningPubKey` as an empty string, to indicate that the transaction is multi-signed.
|
||||||
|
|
||||||
|
Keep in mind that the `Fee` for multi-signed transactions is significantly higher than for regularly-signed transactions. It should be (N+1) times the normal [transaction cost](concept-transaction-cost.html), where N is the number of signatures you plan to provide. Given that it sometimes takes a while to collect signatures from multiple sources, you may want to include additional buffer in case the [transaction cost's load scaling](concept-transaction-cost.html#load-scaling) increases in that time.
|
||||||
|
|
||||||
|
Here's an example transaction ready to be multi-signed:
|
||||||
|
|
||||||
{
|
{
|
||||||
"TransactionType": "TrustSet",
|
"TransactionType": "TrustSet",
|
||||||
"Account": "rnBFvgZphmN39GWzUJeUitaP22Fr9be75H",
|
"Account": "rEuLyBCvcw4CFmzv8RepSiAoNgF8tTGJQC",
|
||||||
"Flags": 262144,
|
"Flags": 262144,
|
||||||
"LimitAmount": {
|
"LimitAmount": {
|
||||||
"currency": "USD",
|
"currency": "USD",
|
||||||
"issuer": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
"issuer": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
|
||||||
"value": "100"
|
"value": "100"
|
||||||
},
|
},
|
||||||
"Sequence": 2,
|
"Sequence": 2,
|
||||||
"SigningPubKey":"",
|
"SigningPubKey": "",
|
||||||
"Fee": "30000"
|
"Fee": "30000"
|
||||||
}
|
}
|
||||||
|
|
||||||
(If you started from a fresh ledger, you first need to fund the account
|
(This transaction creates an accounting relationship from rEuLyBCvcw4CFmzv8RepSiAoNgF8tTGJQC to rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh with a maximum balance of 100 USD.)
|
||||||
specified by the `issuer` in this example, and then manually close the ledger.)
|
|
||||||
|
|
||||||
Keep in mind that the `Fee` for multi-signed transactions is significantly
|
|
||||||
higher than for regularly-signed transactions. It should be (N+1) times the
|
|
||||||
normal fee, where N is the number of signatures you plan to provide. Given that
|
|
||||||
it sometimes takes a while to collect signatures from multiple sources, you may
|
|
||||||
want to include additional buffer in case the load fee increases in that time.
|
|
||||||
|
|
||||||
|
|
||||||
## 8. Get one signature ##
|
### 2. Get one signature ###
|
||||||
|
|
||||||
The [`sign_for` command](reference-rippled.html#sign-for) takes an address and related secret, and a transaction in JSON form. It generates a signature for that transaction, using the secret key and address specified. By using this, you can provide signatures that contribute to a multi-signed transaction. (The signatures should come from the members of your SignerList.)
|
Use the [`sign_for` command](reference-rippled.html#sign-for) with the secret key and address of one of the members of your SignerList to get a signature for that member.
|
||||||
|
|
||||||
$ 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" }'
|
**Caution:** Never submit a secret key to a server you do not control. Do not transmit a secret key unencrypted over the network.
|
||||||
|
|
||||||
|
$ 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"
|
Loading: "/home/mduo13/.config/ripple/rippled.cfg"
|
||||||
Connecting to 127.0.0.1:5005
|
Connecting to 127.0.0.1:5005
|
||||||
{
|
{
|
||||||
@@ -345,14 +310,17 @@ The [`sign_for` command](reference-rippled.html#sign-for) takes an address and r
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Save the `tx_json` field of the response: it has the new signature in the `Signers` field.
|
Save the `tx_json` field of the response: it has the new signature in the `Signers` field. You can discard the value of the `tx_blob` field.
|
||||||
|
|
||||||
The `tx_blob` is not very useful at this point, unless you're "multi-signing" a transaction with only one signature.
|
|
||||||
|
|
||||||
|
|
||||||
## 9. Get additional signatures the same way ##
|
### 3. Get additional signatures ###
|
||||||
|
|
||||||
You can collect additional signatures for the same transaction in parallel by using the `sign_for` command with the same transaction JSON. You can also collect additional signatures in serial: if you provide the `tx_json` value from a previous `sign_for` response, the response appends a signature to the existing Signers array.
|
You can collect additional signatures in parallel or in serial:
|
||||||
|
|
||||||
|
* In parallel: Use the `sign_for` command with the original JSON for the transaction. Each response has a single signature in the `Signers` array.
|
||||||
|
* In serial: Use the `sign_for` command with the `tx_json` value from the previous `sign_for` response. Each response adds a new signature to the existing `Signers` array.
|
||||||
|
|
||||||
|
**Caution:** Never submit a secret key to a server you do not control. Do not transmit a secret key unencrypted over the network.
|
||||||
|
|
||||||
$ rippled sign_for rUpy3eEg8rqjqfUoLeBnZkscbKbFsKXC3v <rUpy..'s secret> '{
|
$ rippled sign_for rUpy3eEg8rqjqfUoLeBnZkscbKbFsKXC3v <rUpy..'s secret> '{
|
||||||
> "Account" : "rEuLyBCvcw4CFmzv8RepSiAoNgF8tTGJQC",
|
> "Account" : "rEuLyBCvcw4CFmzv8RepSiAoNgF8tTGJQC",
|
||||||
@@ -416,14 +384,14 @@ You can collect additional signatures for the same transaction in parallel by us
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Depending on the SignerList you configured, you may need to repeat this step several times in order to get signatures from all the necessary parties.
|
Depending on the SignerList you configured, you may need to repeat this step several times to get signatures from all the necessary parties.
|
||||||
|
|
||||||
|
|
||||||
## 10. Combine the signatures and submit ##
|
### 4. Combine signatures and submit ###
|
||||||
|
|
||||||
The commandline syntax for the [`submit_multisigned` command](reference-rippled.html#submit-multisigned) takes a single transaction JSON containing a `Signers` array, so you need to combine all the signatures from the all the responses into a single `Signers` array field with all the signatures. If you collected signatures serially, the `tx_json` from the last response is sufficient.
|
If you collected the signatures in serial, the `tx_json` from the last `sign_for` response has all the signatures assembled, so you can use that as the argument to the [`submit_multisigned` command](reference-rippled.html#submit-multisigned).
|
||||||
|
|
||||||
The `submit_multisigned` command actually submits the transaction for inclusion in the ledger. In online mode, this also relays it to other members of the network.
|
If you collected the signatures in parallel, you must manually construct a `tx_json` object with all the signatures included. Take the `Signers` arrays from all the `sign_for` responses, and combine their contents into a single `Signers` array that has each signature. Add the combined `Signers` array to the original transaction JSON value, and use that as the argument to the [`submit_multisigned` command](reference-rippled.html#submit-multisigned).
|
||||||
|
|
||||||
$ rippled submit_multisigned '{
|
$ rippled submit_multisigned '{
|
||||||
> "Account" : "rEuLyBCvcw4CFmzv8RepSiAoNgF8tTGJQC",
|
> "Account" : "rEuLyBCvcw4CFmzv8RepSiAoNgF8tTGJQC",
|
||||||
@@ -498,11 +466,11 @@ The `submit_multisigned` command actually submits the transaction for inclusion
|
|||||||
Take note of the `hash` value from the response so you can check the results of the transaction later. (In this case, the hash is `BD636194C48FD7A100DE4C972336534C8E710FD008C0F3CF7BC5BF34DAF3C3E6`.)
|
Take note of the `hash` value from the response so you can check the results of the transaction later. (In this case, the hash is `BD636194C48FD7A100DE4C972336534C8E710FD008C0F3CF7BC5BF34DAF3C3E6`.)
|
||||||
|
|
||||||
|
|
||||||
## 14. Close the ledger one last time ##
|
### 5. Close the ledger ##
|
||||||
|
|
||||||
As before, on the live network, you can wait 4-7 seconds for the ledger to close automatically.
|
If you are using the live network, you can wait 4-7 seconds for the ledger to close automatically.
|
||||||
|
|
||||||
If running `rippled` in stand-alone mode, use the [`ledger_accept` command](reference-rippled.html#ledger-accept) to manually close the ledger:
|
If you're running `rippled` in stand-alone mode, use the [`ledger_accept` command](reference-rippled.html#ledger-accept) to manually close the ledger:
|
||||||
|
|
||||||
$ rippled ledger_accept
|
$ rippled ledger_accept
|
||||||
Loading: "/home/mduo13/.config/ripple/rippled.cfg"
|
Loading: "/home/mduo13/.config/ripple/rippled.cfg"
|
||||||
@@ -515,9 +483,13 @@ If running `rippled` in stand-alone mode, use the [`ledger_accept` command](refe
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
## 15. Confirm the results of the transaction ##
|
### 6. Confirm transaction results ###
|
||||||
|
|
||||||
Use the hash value from the response to the `submit_multisigned` command.
|
Use the hash value from the response to the `submit_multisigned` command to look up the transaction using the [`tx` command](reference-rippled.html#tx). In particular, check that the `TransactionResult` is the string `tesSUCCESS`.
|
||||||
|
|
||||||
|
On the live network, you must also confirm that the `validated` field is set to the boolean `true`. If the field is not `true`, 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.
|
||||||
|
|
||||||
|
In stand-alone mode, the server automatically considers a ledger to be `validated` if it has been manually closed.
|
||||||
|
|
||||||
$ rippled tx BD636194C48FD7A100DE4C972336534C8E710FD008C0F3CF7BC5BF34DAF3C3E6
|
$ rippled tx BD636194C48FD7A100DE4C972336534C8E710FD008C0F3CF7BC5BF34DAF3C3E6
|
||||||
Loading: "/home/mduo13/.config/ripple/rippled.cfg"
|
Loading: "/home/mduo13/.config/ripple/rippled.cfg"
|
||||||
@@ -629,10 +601,3 @@ Use the hash value from the response to the `submit_multisigned` command.
|
|||||||
"validated": true
|
"validated": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
In particular, check that the `TransactionResult` is the string `tesSUCCESS`.
|
|
||||||
|
|
||||||
On the live network, you must also confirm that the `validated` field is set to the boolean `true`. If the field is not `true`, 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.
|
|
||||||
|
|
||||||
In stand-alone mode, the server automatically considers a ledger to be `validated` if it has been manually closed.
|
|
||||||
|
|||||||
@@ -1059,6 +1059,7 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
<p>The <code>SignerEntries</code> may be any combination of funded and unfunded addresses that use either secp256k1 or ed25519 keys.</p>
|
||||||
<h3 id="signerentry-object">SignerEntry object</h3>
|
<h3 id="signerentry-object">SignerEntry object</h3>
|
||||||
<p>Each member of the <code>SignerEntries</code> field is an object that describes that signer in the list. A SignerEntry has the following fields:</p>
|
<p>Each member of the <code>SignerEntries</code> field is an object that describes that signer in the list. A SignerEntry has the following fields:</p>
|
||||||
<table>
|
<table>
|
||||||
|
|||||||
@@ -7320,6 +7320,8 @@ rippled sign sssssssssssssssssssssssssssss '{"TransactionType": "Payment", "Acco
|
|||||||
<li><code>tooBusy</code> - The transaction did not include paths, but the server is too busy to do pathfinding right now. Does not occur if you are connected as an admin.</li>
|
<li><code>tooBusy</code> - The transaction did not include paths, but the server is too busy to do pathfinding right now. Does not occur if you are connected as an admin.</li>
|
||||||
<li><code>noPath</code> - The transaction did not include paths, and the server was unable to find a path by which this payment can occur.</li>
|
<li><code>noPath</code> - The transaction did not include paths, and the server was unable to find a path by which this payment can occur.</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
<h2 id="sign-for">sign_for</h2>
|
||||||
|
<p>The <code>sign_for</code> command provides one signature for a multi-signed transaction. takes an address and related secret, and a transaction in JSON form. (TODO: finish this section.) It generates a signature for that transaction, using the secret key and address specified. By using this, you can provide signatures that contribute to a multi-signed transaction. (The signatures should come from the members of your SignerList.)</p>
|
||||||
<h2 id="submit">submit</h2>
|
<h2 id="submit">submit</h2>
|
||||||
<p><a href="https://github.com/ripple/rippled/blob/master/src/ripple/rpc/handlers/Submit.cpp" title="Source">[Source]<br/></a></p>
|
<p><a href="https://github.com/ripple/rippled/blob/master/src/ripple/rpc/handlers/Submit.cpp" title="Source">[Source]<br/></a></p>
|
||||||
<p>The <code>submit</code> method sends a <a href="reference-transaction-format.html">transaction</a> to the network to be confirmed and included in future ledgers.</p>
|
<p>The <code>submit</code> method sends a <a href="reference-transaction-format.html">transaction</a> to the network to be confirmed and included in future ledgers.</p>
|
||||||
@@ -7588,6 +7590,8 @@ submit sssssssssssssssssssssssssssss '{"TransactionType":"Payment", "Account":"r
|
|||||||
<li><code>internalSubmit</code> - An internal error occurred when submitting the transaction. This could be caused by many aspects of the transaction, including a bad signature or some fields being malformed.</li>
|
<li><code>internalSubmit</code> - An internal error occurred when submitting the transaction. This could be caused by many aspects of the transaction, including a bad signature or some fields being malformed.</li>
|
||||||
<li><code>internalJson</code> - An internal error occurred when serializing the transaction to JSON. This could be caused by many aspects of the transaction, including a bad signature or some fields being malformed.</li>
|
<li><code>internalJson</code> - An internal error occurred when serializing the transaction to JSON. This could be caused by many aspects of the transaction, including a bad signature or some fields being malformed.</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
<h2 id="submit-multisigned">submit_multisigned</h2>
|
||||||
|
<p>The <code>submit_multisigned</code> command takes a transaction specification with multiple signatures and applies that transaction. (TODO: finish this section.)</p>
|
||||||
<h2 id="book-offers">book_offers</h2>
|
<h2 id="book-offers">book_offers</h2>
|
||||||
<p><a href="https://github.com/ripple/rippled/blob/develop/src/ripple/rpc/handlers/BookOffers.cpp" title="Source">[Source]<br/></a></p>
|
<p><a href="https://github.com/ripple/rippled/blob/develop/src/ripple/rpc/handlers/BookOffers.cpp" title="Source">[Source]<br/></a></p>
|
||||||
<p>The <code>book_offers</code> method retrieves a list of offers, also known as the <a href="http://www.investopedia.com/terms/o/order-book.asp">order book</a>, between two currencies. If the results are very large, a partial result is returned with a marker so that subsequent requests can resume from where the previous one left off.</p>
|
<p>The <code>book_offers</code> method retrieves a list of offers, also known as the <a href="http://www.investopedia.com/terms/o/order-book.asp">order book</a>, between two currencies. If the results are very large, a partial result is returned with a marker so that subsequent requests can resume from where the previous one left off.</p>
|
||||||
|
|||||||
@@ -147,15 +147,36 @@
|
|||||||
</ul>
|
</ul>
|
||||||
<p>Transactions are only valid if signed, submitted, and accepted into a validated ledger version. There are many ways a transaction can fail.</p>
|
<p>Transactions are only valid if signed, submitted, and accepted into a validated ledger version. There are many ways a transaction can fail.</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="#signing-and-sending-transactions">Signing and Sending Transactions</a></li>
|
<li><a href="#authorizing-transactions">Authorized Transactions</a></li>
|
||||||
<li><a href="#reliable-transaction-submission">Reliable Transaction Submission</a></li>
|
<li><a href="#reliable-transaction-submission">Reliable Transaction Submission</a></li>
|
||||||
<li><a href="#transaction-results">Transaction Results - How to find and interpret transaction results</a></li>
|
<li><a href="#transaction-results">Transaction Results - How to find and interpret transaction results</a></li>
|
||||||
<li><a href="#full-transaction-response-list">Full Transaction Response List - Complete table of all error codes</a></li>
|
<li><a href="#full-transaction-response-list">Full Transaction Response List - Complete table of all error codes</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
<h2 id="signing-and-sending-transactions">Signing and Sending Transactions</h2>
|
<h2 id="authorizing-transactions">Authorizing Transactions</h2>
|
||||||
<p>Signing a transaction cryptographically proves that the person in charge of the account sending the transaction is authorized to do so. Only signed transactions can be submitted to the network and included in a validated ledger. A signed transaction is immutable: its contents cannot change, and the signature is not valid for any other transaction.</p>
|
<p>In the decentralized Ripple Consensus Ledger, a digital signature proves that a transaction is authorized to perform a specific set of actions. Only signed transactions can be submitted to the network and included in a validated ledger. A signed transaction is immutable: its contents cannot change, and the signature is not valid for any other transaction.</p>
|
||||||
<p>You sign a transaction using a secret key: either the master secret, or a regular secret if the account has a regular key pair associated with it. (See <a href="#setregularkey">SetRegularKey</a> for details.) If your account has a SignerList associated with it, you can use a <a href="#multi-signing">multi-signature</a> instead.</p>
|
<p>A transaction can be authorized by any of the following types of signatures:</p>
|
||||||
<p>Typically, you create a transaction in JSON format first. Here is an example of an unsigned Payment-type transaction in JSON:</p>
|
<ul>
|
||||||
|
<li>A single signature from the master secret key that is mathematically associated with the address. You can disable or enable the master key using an <a href="#accountset">AccountSet transaction</a>.</li>
|
||||||
|
<li>A single signature that matches a regular key enabled for the address. You can enable, remove, or replace a regular key using a <a href="#setregularkey">SetRegularKey transaction</a>.</li>
|
||||||
|
<li>A <a href="#multi-signing">multi-signature</a> that matches a list of signers enabled for the address. You can enable, remove, or replace a list of signers using a <a href="#SignerListSet">SignerListSet transaction</a>.</li>
|
||||||
|
</ul>
|
||||||
|
<p>Any signature type can authorize any type of transaction, with the following exceptions:</p>
|
||||||
|
<ul>
|
||||||
|
<li>Only the master key can <a href="#accountset-flags">disable the master key</a>.</li>
|
||||||
|
<li>Only the master key can <a href="concept-freeze.html#no-freeze">permanently give up the ability to freeze</a>.</li>
|
||||||
|
<li>You can never remove the last method of signing transactions from an address.</li>
|
||||||
|
</ul>
|
||||||
|
<h2 id="signing-and-submitting-transactions">Signing and Submitting Transactions</h2>
|
||||||
|
<p>Sending a transaction to the Ripple Consensus Ledger involves several steps:</p>
|
||||||
|
<ol>
|
||||||
|
<li>Create an unsigned transaction in JSON format.</li>
|
||||||
|
<li>Use one or more signatures to <a href="#authorizing-transactions">authorize the transaction</a>.</li>
|
||||||
|
<li>Submit a transaction to a <code>rippled</code> server. If the transaction is properly formed, the server provisionally applies the transaction to its current version of the ledger and relays the transaction to other members of the peer-to-peer network.</li>
|
||||||
|
<li>The <a href="https://ripple.com/knowledge_center/the-ripple-ledger-consensus-process/">consensus process</a> determines which provisional transactions get included in the next validated ledger.</li>
|
||||||
|
<li>The <code>rippled</code> servers apply those transactions to the previous ledger in a canonical order and share their results.</li>
|
||||||
|
<li>If enough <a href="tutorial-rippled-setup.html#reasons-to-run-a-validator">trusted validators</a> created the exact same ledger, that ledger is declared <em>validated</em> and the <a href="#transaction-results">results of the transactions</a> in that ledger are immutable.</li>
|
||||||
|
</ol>
|
||||||
|
<p>Here is an example of an unsigned <a href="#payment">Payment-type transaction</a> in JSON:</p>
|
||||||
<pre><code>{
|
<pre><code>{
|
||||||
"TransactionType" : "Payment",
|
"TransactionType" : "Payment",
|
||||||
"Account" : "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
"Account" : "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||||
@@ -276,28 +297,9 @@
|
|||||||
}
|
}
|
||||||
</code></pre>
|
</code></pre>
|
||||||
<h3 id="multi-signing">Multi-Signing</h3>
|
<h3 id="multi-signing">Multi-Signing</h3>
|
||||||
<p>Multi-signing in Ripple is the act of authorizing transactions for the Ripple
|
<p>Multi-signing in Ripple is the act of <a href="#authorizing-transactions">authorizing transactions</a> for the Ripple Consensus Ledger by using a combination of multiple secret keys. Multi-signing is due to be enabled by an <a href="concept-amendments.html">Amendment</a> to the Ripple Consensus Protocol. You can use multi-signing in addition to, or instead of, a master key, a <a href="#setregularkey">regular key</a>, or both.</p>
|
||||||
Consensus Ledger by using a combination of multiple secret keys. Multi-signing
|
<p>The <a href="#signerlistset">SignerListSet transaction</a> defines which addresses can authorize transactions from your address. You can include up to 8 addresses in a SignerList. You can achieve several different configurations using the weight and quorum values of the signer list.</p>
|
||||||
allows various use cases including:</p>
|
<p>For more information, see <a href="tutorial-multisign.html">How to Multi-Sign</a>.</p>
|
||||||
<ul>
|
|
||||||
<li>If you require keys from different devices, a malicious user must compromise multiple machines in order to send transactions on your behalf.</li>
|
|
||||||
<li>If the keys to an account are in the custody of entirely different people, those people must collaborate in order to send transaction from that account.</li>
|
|
||||||
<li>Delegate a group of others who can send transactions for you if you are unavailable or unable to sign normally.</li>
|
|
||||||
<li>... and more.</li>
|
|
||||||
</ul>
|
|
||||||
<p>To set up multi-signing for an account, the process is straightforward:</p>
|
|
||||||
<ol>
|
|
||||||
<li>Use a <a href="#signerlistset">SignerListSet transaction</a> to define which accounts or keys can, together, authorize transactions for this account.</li>
|
|
||||||
<li>Optionally disable the master key with an <a href="#accountset">AccountSet transaction</a> using the <code>asfDisableMaster</code> flag.</li>
|
|
||||||
<li>Optionally remove the existing regular key (if any) with a <a href="#setregularkey">SetRegularKey transaction</a>.</li>
|
|
||||||
</ol>
|
|
||||||
<p>After an account has a SignerList associated with it, the process of submitting a multi-signed transaction is as follows:</p>
|
|
||||||
<ol>
|
|
||||||
<li>Create the transaction to be signed as a JSON object</li>
|
|
||||||
<li>Generate a signature for each account using the <a href="rippled-apis.html#sign-for"><code>sign_for</code> command</a>.</li>
|
|
||||||
<li>Combine the signatures and submit using the <a href="rippled-apis.html#submit-multisigned"><code>submit_multisigned</code> command</a>.</li>
|
|
||||||
</ol>
|
|
||||||
<p>Main article: <a href="multisign.html">How to Multi-Sign</a></p>
|
|
||||||
<h3 id="reliable-transaction-submission">Reliable Transaction Submission</h3>
|
<h3 id="reliable-transaction-submission">Reliable Transaction Submission</h3>
|
||||||
<p>Reliably submitting transactions is the process of achieving both of the following:</p>
|
<p>Reliably submitting transactions is the process of achieving both of the following:</p>
|
||||||
<ul>
|
<ul>
|
||||||
@@ -883,7 +885,7 @@ allows various use cases including:</p>
|
|||||||
<p>In rippled's WebSocket and JSON-RPC APIs, the TransferRate is represented as an integer, the amount that must be sent in order for 1 billion units to arrive. For example, a 20% transfer fee is represented as the value <code>1200000000</code>. The value cannot be less than 1000000000. (Less than that would indicate giving away money for sending transactions, which is exploitable.) You can specify 0 as a shortcut for 1000000000, meaning no fee.</p>
|
<p>In rippled's WebSocket and JSON-RPC APIs, the TransferRate is represented as an integer, the amount that must be sent in order for 1 billion units to arrive. For example, a 20% transfer fee is represented as the value <code>1200000000</code>. The value cannot be less than 1000000000. (Less than that would indicate giving away money for sending transactions, which is exploitable.) You can specify 0 as a shortcut for 1000000000, meaning no fee.</p>
|
||||||
<h2 id="setregularkey">SetRegularKey</h2>
|
<h2 id="setregularkey">SetRegularKey</h2>
|
||||||
<p><a href="https://github.com/ripple/rippled/blob/4239880acb5e559446d2067f00dabb31cf102a23/src/ripple/app/transactors/SetRegularKey.cpp" title="Source">[Source]<br/></a></p>
|
<p><a href="https://github.com/ripple/rippled/blob/4239880acb5e559446d2067f00dabb31cf102a23/src/ripple/app/transactors/SetRegularKey.cpp" title="Source">[Source]<br/></a></p>
|
||||||
<p>A SetRegularKey transaction changes the regular key used by the account to sign future transactions.</p>
|
<p>A SetRegularKey transaction changes the regular key associated with an address.</p>
|
||||||
<pre><code>{
|
<pre><code>{
|
||||||
"Flags": 0,
|
"Flags": 0,
|
||||||
"TransactionType": "SetRegularKey",
|
"TransactionType": "SetRegularKey",
|
||||||
@@ -905,14 +907,15 @@ allows various use cases including:</p>
|
|||||||
<tr>
|
<tr>
|
||||||
<td>RegularKey</td>
|
<td>RegularKey</td>
|
||||||
<td>String</td>
|
<td>String</td>
|
||||||
<td>Account</td>
|
<td>AccountID</td>
|
||||||
<td>(Optional) The public key of a new keypair, to use as the regular key to this account, as a base-58-encoded string in the same format as an account address. If omitted, removes the existing regular key.</td>
|
<td>(Optional) A base-58-encoded <a href="reference-rippled.html#addresses">Ripple address</a> to use as the regular key. If omitted, removes the existing regular key.</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<p>Instead of using an account's master key to sign transactions, you can set an alternate key pair, called the "Regular Key". As long as the public key for this key pair is set in the <code>RegularKey</code> field of an account this way, then the secret of the Regular Key pair can be used to sign transactions. (Other methods of signing transactions can also be used, including <a href="#multi-signing">multi-signing</a> or the master key.</p>
|
<p>In addition to the master key, which is mathematically-related to an address, you can associate <strong>at most 1 additional key pair</strong> with an address using this type of transaction. The additional key pair is called a <em>regular key</em>. If your address has a regular key pair defined, you can use the secret key of the regular key pair to <a href="#authorizing-transactions">authorize transactions</a>.</p>
|
||||||
<p>A Regular Key pair is generated in the same way as any other Ripple keys (for example, with <a href="rippled-apis.html#wallet-propose">wallet_propose</a>), but it can be changed. A Master Key pair is an intrinsic part of the account's identity (the address is derived from the master public key). The Master Key can be <a href="#accountset-flags">disabled</a> but it cannot be changed. Therefore, it is beneficial to security sign transactions with a Regular Key instead of the master key whenever possible. For even greater security, you can use <a href="#multi-signing">multi-signing</a>, but multi-signing costs additional XRP in transaction fees and reserves.</p>
|
<p>A regular key pair is generated in the same way as any other Ripple keys (for example, with <a href="reference-rippled.html#wallet-propose">wallet_propose</a>), but it can be changed. A master key pair is an intrinsic part of an address's identity (the address is derived from the master public key). You can <a href="#accountset-flags">disable</a> a master key but you cannot change it.</p>
|
||||||
<p>If your regular key is compromised, but the master key is not, you can use a SetRegularKey transaction to regain control of your account. In some cases, you can even send a <a href="concept-transaction-cost.html#key-reset-transaction">key reset transaction</a> without paying the <a href="#transaction-cost">transaction cost</a>.</p>
|
<p>You can protect your master secret by using a regular key instead of the master key to sign transactions where possible. If your regular key is compromised, but the master key is not, you can use a SetRegularKey transaction to regain control of your address. In some cases, you can even send a <a href="concept-transaction-cost.html#key-reset-transaction">key reset transaction</a> without paying the <a href="#transaction-cost">transaction cost</a>.</p>
|
||||||
|
<p>For even greater security, you can use <a href="#multi-signing">multi-signing</a>, but multi-signing requires additional XRP for the <a href="concept-transaction-cost.html">transaction cost</a> and <a href="concept-reserves.html">reserve</a>.</p>
|
||||||
<h2 id="offercreate">OfferCreate</h2>
|
<h2 id="offercreate">OfferCreate</h2>
|
||||||
<p><a href="https://github.com/ripple/rippled/blob/master/src/ripple/app/tx/impl/CreateOffer.cpp" title="Source">[Source]<br/></a></p>
|
<p><a href="https://github.com/ripple/rippled/blob/master/src/ripple/app/tx/impl/CreateOffer.cpp" title="Source">[Source]<br/></a></p>
|
||||||
<p>An OfferCreate transaction is effectively a <a href="http://en.wikipedia.org/wiki/limit_order">limit order</a>. It defines an intent to exchange currencies, and creates an Offer node in the Ripple Consensus Ledger if not completely fulfilled when placed. Offers can be partially fulfilled.</p>
|
<p>An OfferCreate transaction is effectively a <a href="http://en.wikipedia.org/wiki/limit_order">limit order</a>. It defines an intent to exchange currencies, and creates an Offer node in the Ripple Consensus Ledger if not completely fulfilled when placed. Offers can be partially fulfilled.</p>
|
||||||
@@ -1202,7 +1205,7 @@ allows various use cases including:</p>
|
|||||||
</table>
|
</table>
|
||||||
<h2 id="signerlistset">SignerListSet</h2>
|
<h2 id="signerlistset">SignerListSet</h2>
|
||||||
<p><a href="https://github.com/ripple/rippled/blob/ef511282709a6a0721b504c6b7703f9de3eecf38/src/ripple/app/tx/impl/SetSignerList.cpp" title="Source">[Source]<br/></a></p>
|
<p><a href="https://github.com/ripple/rippled/blob/ef511282709a6a0721b504c6b7703f9de3eecf38/src/ripple/app/tx/impl/SetSignerList.cpp" title="Source">[Source]<br/></a></p>
|
||||||
<p>The SignerListSet transaction creates, modifies, or removes a list of signers that can be used to multi-sign a transaction.</p>
|
<p>The SignerListSet transaction creates, modifies, or removes a list of signers that can be used to <a href="#multi-signing">multi-sign</a> a transaction.</p>
|
||||||
<p>Example SignerListSet:</p>
|
<p>Example SignerListSet:</p>
|
||||||
<pre><code>{
|
<pre><code>{
|
||||||
"Flags": 0,
|
"Flags": 0,
|
||||||
@@ -1252,13 +1255,14 @@ allows various use cases including:</p>
|
|||||||
<td>SignerEntries</td>
|
<td>SignerEntries</td>
|
||||||
<td>Array</td>
|
<td>Array</td>
|
||||||
<td>Array</td>
|
<td>Array</td>
|
||||||
<td>(Omitted when deleting) Array of <a href="ripple-ledger.html#signerentry-object">SignerEntry objects</a>, indicating the addresses and weights of signers in this list. A SignerList must have at least 1 member and no more than 8 members. No address may appear more than once in the list, nor may the <code>Account</code> submitting the transaction appear in the list.</td>
|
<td>(Omitted when deleting) Array of <a href="reference-ledger-format.html#signerentry-object">SignerEntry objects</a>, indicating the addresses and weights of signers in this list. A SignerList must have at least 1 member and no more than 8 members. No address may appear more than once in the list, nor may the <code>Account</code> submitting the transaction appear in the list.</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<p>An account may not have more than one SignerList. A successful SignerListSet transaction replaces the existing SignerList, if one exists. To delete a SignerList, you must set <code>SignerQuorum</code> to <code>0</code> <em>and</em> omit the <code>SignerEntries</code> field. Otherwise, the transaction fails with the error <a href="#tem-codes">temMALFORMED</a>. A transaction to delete a SignerList is considered successful even if there was no SignerList to delete.</p>
|
<p>An account may not have more than one SignerList. A successful SignerListSet transaction replaces the existing SignerList, if one exists. To delete a SignerList, you must set <code>SignerQuorum</code> to <code>0</code> <em>and</em> omit the <code>SignerEntries</code> field. Otherwise, the transaction fails with the error <a href="#tem-codes">temMALFORMED</a>. A transaction to delete a SignerList is considered successful even if there was no SignerList to delete.</p>
|
||||||
<p>You cannot create a SignerList such that the SignerQuorum could never be met. The SignerQuorum must be greater than 0 but less than or equal to the sum of the <code>SignerWeight</code> values in the list. Otherwise, the transaction fails with the error <a href="#tem-codes">temMALFORMED</a>.</p>
|
<p>You cannot create a SignerList such that the SignerQuorum could never be met. The SignerQuorum must be greater than 0 but less than or equal to the sum of the <code>SignerWeight</code> values in the list. Otherwise, the transaction fails with the error <a href="#tem-codes">temMALFORMED</a>.</p>
|
||||||
<p>You cannot remove the last method of signing transactions from an account. If an account's master key is disabled (it has the <a href="ripple-ledger.html#accountroot-flags"><code>lsfDisableMaster</code> flag</a> enabled) and the account does not have a Regular Key configured, then you cannot delete the SignerList from the account. Instead, the transaction fails with the error <a href="#tec-codes">tecNO_ALTERNATIVE_KEY</a>.</p>
|
<p>You can create, update, or remove a SignerList using the master key, regular key, or the current SignerList, if those methods of signing transactions are available.</p>
|
||||||
|
<p>You cannot remove the last method of signing transactions from an account. If an account's master key is disabled (it has the <a href="ripple-ledger.html#accountroot-flags"><code>lsfDisableMaster</code> flag</a> enabled) and the account does not have a <a href="#setregularkey">Regular Key</a> configured, then you cannot delete the SignerList from the account. Instead, the transaction fails with the error <a href="#tec-codes">tecNO_ALTERNATIVE_KEY</a>.</p>
|
||||||
<h1 id="pseudo-transactions">Pseudo-Transactions</h1>
|
<h1 id="pseudo-transactions">Pseudo-Transactions</h1>
|
||||||
<p>Pseudo-Transactions are never submitted by users, nor propagated through the network. Instead, a server may choose to inject them in a proposed ledger directly. If enough servers inject an equivalent pseudo-transaction for it to pass consensus, then it becomes included in the ledger, and appears in ledger data thereafter.</p>
|
<p>Pseudo-Transactions are never submitted by users, nor propagated through the network. Instead, a server may choose to inject them in a proposed ledger directly. If enough servers inject an equivalent pseudo-transaction for it to pass consensus, then it becomes included in the ledger, and appears in ledger data thereafter.</p>
|
||||||
<p>Some of the fields that are mandatory for normal transactions do not make sense for pseudo-transactions. In those cases, the pseudo-transaction has the following default values:</p>
|
<p>Some of the fields that are mandatory for normal transactions do not make sense for pseudo-transactions. In those cases, the pseudo-transaction has the following default values:</p>
|
||||||
|
|||||||
@@ -126,92 +126,60 @@
|
|||||||
</aside>
|
</aside>
|
||||||
<main class="main" role="main">
|
<main class="main" role="main">
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<h1 id="introduction-to-multi-signing">Introduction to Multi-Signing</h1>
|
<h1 id="how-to-multi-sign">How to Multi-Sign</h1>
|
||||||
<p>Multi-signing in Ripple is the act of authorizing transactions for the Ripple Consensus Ledger by using a combination of multiple secret keys. After setting up multi-signing for an account, you can put the master secret in cold storage, or even disable the master key entirely. With multiple secret keys required to authorize a multi-signature, you can improve security in several ways.</p>
|
<p>Multi-signing is one of three ways to authorize transactions for the Ripple Consensus 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>
|
<ul>
|
||||||
<li>If you keep an account's keys on different devices, a malicious user must compromise multiple machines in order to send transactions on your behalf.</li>
|
<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>If the keys to an account are in the custody of entirely different people, those people must collaborate in order to send transaction from that account.</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 use the SignerList as a backup, to delegate a group of others who can send transactions for you if you are unavailable or unable to sign using your regular key.</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>Even more uses than can be described here.</li>
|
<li>... and more.</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
<p>To use multi-signing:</p>
|
||||||
|
<ol>
|
||||||
|
<li><a href="#availability-of-multi-signing">The Ripple peer-to-peer network must have multi-signing enabled.</a></li>
|
||||||
|
<li><a href="#setting-up-multi-sign">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>
|
<h2 id="availability-of-multi-signing">Availability of Multi-Signing</h2>
|
||||||
<p>Multi-signing is built into <code>rippled</code> starting with version <strong>0.31.0</strong>. Because multi-signing is a change in transaction processing, the change is due to be enabled by an <strong>Amendment</strong> to the Ripple Consensus Protocol. This Amendment must be approved by a consensus of validators showing consistent support for the feature over a period of time. For more information, see <a href="concept-amendments.html">Amendments</a>.</p>
|
<p>Multi-signing is built into <code>rippled</code> starting with version <strong>0.31.0</strong>. Because multi-signing is a change in transaction processing, the change is due to be enabled by an <strong>Amendment</strong> to the Ripple Consensus Protocol. This Amendment must be approved by a consensus of validators showing consistent support for the feature over a period of time. For more information, see <a href="concept-amendments.html">Amendments</a>.</p>
|
||||||
<p>You can test multi-signing by running <code>rippled</code> in <a href="concept-stand-alone-mode.html">stand-alone mode</a> with the Multi-Sign feature enabled. To enable Multi-Sign for testing, add the following stanza to your <code>rippled.cfg</code>:</p>
|
<p>If you want to test multi-signing before it becomes available in the production network, or without risking real money, you can do so by running <code>rippled</code> in <a href="concept-stand-alone-mode.html">stand-alone mode</a> with the MultiSign feature enabled. To enable multi-signing for testing, add the following stanza to your <code>rippled.cfg</code>:</p>
|
||||||
<pre><code>[features]
|
<pre><code>[features]
|
||||||
MultiSign
|
MultiSign
|
||||||
</code></pre>
|
</code></pre>
|
||||||
<h1 id="how-to-multi-sign">How to Multi-Sign</h1>
|
<h2 id="setting-up-multi-signing">Setting up Multi-Signing</h2>
|
||||||
<p>The basic process of Multi-Signing a transaction is necessarily more complex than the process of signing a transaction with a single master key or regular key.</p>
|
<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 Ripple Consensus 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>
|
||||||
<h2 id="1-optional-generate-keys-for-a-new-wallet">1. (Optional) Generate keys for a new wallet</h2>
|
<h3 id="1-prepare-a-funded-address">1. Prepare a funded address</h3>
|
||||||
<p>This step is not strictly necessary. For this process, we generate and fund a new Ripple account and then set up multi-signing for that account. To set up multi-signing on an existing Ripple account, skip ahead to <a href="4-create-a-signerlist-on-the-new-account-with-a-signerlistset-transaction">Step 4: creating a signer list</a>.</p>
|
<p>You need a Ripple 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 Ripple 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
|
<pre><code>$ rippled wallet_propose
|
||||||
Loading: "/home/mduo13/.config/ripple/rippled.cfg"
|
Loading: "/home/mduo13/.config/ripple/rippled.cfg"
|
||||||
Connecting to 127.0.0.1:5005
|
Connecting to 127.0.0.1:5005
|
||||||
{
|
{
|
||||||
"result" : {
|
"result" : {
|
||||||
"account_id" : "rEuLyBCvcw4CFmzv8RepSiAoNgF8tTGJQC",
|
"account_id" : "rnRJ4dpSBKDR2M1itf4Ah6tZZm5xuNZFPH",
|
||||||
"key_type" : "secp256k1",
|
"key_type" : "secp256k1",
|
||||||
"master_key" : "LOST FOUR ALOE ABE SLUG ITS HACK MAGI SOCK BASS APE DELL",
|
"master_key" : "FLOG SEND GOES CUFF GAGE FAT ANTI DEL GUM TIRE ISLE BEAR",
|
||||||
"master_seed" : "sn1CmMEkPijNrfyr8HJqsgP416dr3",
|
"master_seed" : "snheH5UUjU4CWqiNVLny2k21TyKPC",
|
||||||
"master_seed_hex" : "E42AD02985BB56923DFC1D002DB510B3",
|
"master_seed_hex" : "A9F859765EB8614D26809836382AFB82",
|
||||||
"public_key" : "aBQgQDutj8YUc7ZRtfj86dnzPCvPcRHtUszxeCCDMgZ7Zq1Thfri",
|
"public_key" : "aBR4hxFXcDNHnGYvTiqb2KU8TTTV1cYV9wXTAuz2DjBm7S8TYEBU",
|
||||||
"public_key_hex" : "03668837C3DCA0F4858587703524E61BB40128B9F6910B80B4655E152CAEE2E321",
|
"public_key_hex" : "03C09A5D112B393D531E4F092E3A5769A5752129F0A9C55C61B3A226BB9B567B9B",
|
||||||
"status" : "success"
|
"status" : "success"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</code></pre>
|
</code></pre>
|
||||||
<p>As always, be sure that an account's secret key never gets transmitted to anyone you don't trust with full control of that account, and certainly not unencrypted over the network.</p>
|
<p>Take note of the <code>account_id</code> (Ripple Address) and <code>master_seed</code> (Ripple secret key) for each one you generate.</p>
|
||||||
<h2 id="2-fund-the-new-account-with-an-existing-wallet">2. Fund the new account with an existing wallet</h2>
|
<h3 id="3-send-signerlistset-transaction">3. Send SignerListSet transaction</h3>
|
||||||
<p>Again, this step is only necessary if you are setting up a new account to use multi-signing for this example.</p>
|
<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 Ripple address, so that a combination of signatures from the members of that SignerList can multi-sign later transactions on your behalf.</p>
|
||||||
<pre><code>$ rippled submit snoPBrXtMeMyMHUVTgbuqAfg1SUTb '{
|
|
||||||
> "TransactionType": "Payment",
|
|
||||||
> "Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
|
|
||||||
> "Destination": "rEuLyBCvcw4CFmzv8RepSiAoNgF8tTGJQC",
|
|
||||||
> "Amount": "100000000",
|
|
||||||
> "Flags": 2147483648
|
|
||||||
> }'
|
|
||||||
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" : "12000022800000002400000004614000000005F5E10068400000000000000A73210330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD02074473045022100ED13CDD4B8F6BA836F7732A029316393A5D9B50712FE79972236ECAD850F813802203148D8944B0BF3D30A3177EFCE6A9F12B3F5A3C3AFF7B73E9A7D65B370E526EE8114B5F762798A53D543A014CAF8B297CFF8F2F937E88314A3780F5CB5A44D366520FC44055E8ED44D9A2270",
|
|
||||||
"tx_json" : {
|
|
||||||
"Account" : "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
|
|
||||||
"Amount" : "100000000",
|
|
||||||
"Destination" : "rEuLyBCvcw4CFmzv8RepSiAoNgF8tTGJQC",
|
|
||||||
"Fee" : "10",
|
|
||||||
"Flags" : 2147483648,
|
|
||||||
"Sequence" : 4,
|
|
||||||
"SigningPubKey" : "0330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD020",
|
|
||||||
"TransactionType" : "Payment",
|
|
||||||
"TxnSignature" : "3045022100ED13CDD4B8F6BA836F7732A029316393A5D9B50712FE79972236ECAD850F813802203148D8944B0BF3D30A3177EFCE6A9F12B3F5A3C3AFF7B73E9A7D65B370E526EE",
|
|
||||||
"hash" : "64FAA44F671E2CBB4E1E4156FCDA72BA3C32EF951C94EDDFEBEBE8BEC3F55696"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</code></pre>
|
|
||||||
<p>Make sure that the <code>engine_result</code> value in the response is <strong>tesSUCCESS</strong>. Otherwise, the transaction failed.</p>
|
|
||||||
<h2 id="3-close-the-ledger">3. Close the ledger</h2>
|
|
||||||
<p>If you are using the live network, you can wait for the ledger to close automatically as the result of consensus. This typically takes 4-7 seconds.</p>
|
|
||||||
<p>If you are running <code>rippled</code> in stand-alone mode, you must manually close the ledger with the <a href="reference-rippled.html#ledger-accept"><code>ledger_accept</code> command</a>.</p>
|
|
||||||
<pre><code>$ rippled ledger_accept
|
|
||||||
Loading: "/home/mduo13/.config/ripple/rippled.cfg"
|
|
||||||
Connecting to 127.0.0.1:5005
|
|
||||||
{
|
|
||||||
"result" : {
|
|
||||||
"ledger_current_index" : 16061437,
|
|
||||||
"status" : "success"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</code></pre>
|
|
||||||
<h2 id="4-create-a-signerlist-on-the-new-account-with-a-signerlistset-transaction">4. Create a SignerList on the new account with a SignerListSet transaction</h2>
|
|
||||||
<p>Before you can multi-sign transactions, you must associate a SignerList with your account, so that RCL knows which keys can be used to sign for you. You do this with a <a href="reference-transaction-format.html#signerlistset">SignerListSet transaction</a>.</p>
|
|
||||||
<p>The <code>Account</code> values in your SignerList can be the addresses of funded accounts that exist in the ledger, or you can generate new addresses that are not currently in use. For funded accounts in the SignerList, a regular key associated with the account can contribute to a multi-signature, and the master key secret can be used only if it is not disabled. For unfunded addresses, only the master key associated with that address can be used to contribute to a multi-signature.</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>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><strong>Caution:</strong> Never submit a secret key to a server you do not control. Do not transmit a secret key unencrypted over the network.</p>
|
||||||
<pre><code>$ rippled submit shqZZy2Rzs9ZqWTCQAdqc3bKgxnYq '{
|
<pre><code>$ rippled submit shqZZy2Rzs9ZqWTCQAdqc3bKgxnYq '{
|
||||||
> "Flags": 0,
|
> "Flags": 0,
|
||||||
> "TransactionType": "SignerListSet",
|
> "TransactionType": "SignerListSet",
|
||||||
@@ -282,10 +250,11 @@ Connecting to 127.0.0.1:5005
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</code></pre>
|
</code></pre>
|
||||||
<p>Make sure that the <code>engine_result</code> value in the response is <strong>tesSUCCESS</strong>. Otherwise, the transaction failed.</p>
|
<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.</p>
|
||||||
<h2 id="5-close-the-ledger-again">5. Close the ledger again</h2>
|
<p><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>
|
||||||
<p>As before, on the live network, you can wait for the ledger to close automatically.</p>
|
<h3 id="4-close-the-ledger">4. Close the ledger</h3>
|
||||||
<p>If 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>
|
<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
|
<pre><code>$ rippled ledger_accept
|
||||||
Loading: "/home/mduo13/.config/ripple/rippled.cfg"
|
Loading: "/home/mduo13/.config/ripple/rippled.cfg"
|
||||||
Connecting to 127.0.0.1:5005
|
Connecting to 127.0.0.1:5005
|
||||||
@@ -296,8 +265,9 @@ Connecting to 127.0.0.1:5005
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</code></pre>
|
</code></pre>
|
||||||
<h2 id="6-confirm-the-presence-of-the-new-signer-list-using-account-objects">6. Confirm the presence of the new signer list using account_objects</h2>
|
<h3 id="5-confirm-the-new-signer-list">5. Confirm the new signer list</h3>
|
||||||
<p>Normally an account can own many objects of different types (such as trust lines and offers). For this tutorial, we created a new account, so the SignerList is the only object in the response from the <a href="reference-rippled.html#account-objects"><code>account_objects</code> command</a>.</p>
|
<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
|
<pre><code>$ rippled account_objects rEuLyBCvcw4CFmzv8RepSiAoNgF8tTGJQC validated
|
||||||
Loading: "/home/mduo13/.config/ripple/rippled.cfg"
|
Loading: "/home/mduo13/.config/ripple/rippled.cfg"
|
||||||
Connecting to 127.0.0.1:5005
|
Connecting to 127.0.0.1:5005
|
||||||
@@ -334,30 +304,6 @@ Connecting to 127.0.0.1:5005
|
|||||||
"SignerListID" : 0,
|
"SignerListID" : 0,
|
||||||
"SignerQuorum" : 3,
|
"SignerQuorum" : 3,
|
||||||
"index" : "79FD203E4DDDF2EA78B798C963487120C048C78652A28682425E47C96D016F92"
|
"index" : "79FD203E4DDDF2EA78B798C963487120C048C78652A28682425E47C96D016F92"
|
||||||
},
|
|
||||||
{
|
|
||||||
"Balance" : {
|
|
||||||
"currency" : "USD",
|
|
||||||
"issuer" : "rrrrrrrrrrrrrrrrrrrrBZbvji",
|
|
||||||
"value" : "0"
|
|
||||||
},
|
|
||||||
"Flags" : 2162688,
|
|
||||||
"HighLimit" : {
|
|
||||||
"currency" : "USD",
|
|
||||||
"issuer" : "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
|
|
||||||
"value" : "0"
|
|
||||||
},
|
|
||||||
"HighNode" : "0000000000000000",
|
|
||||||
"LedgerEntryType" : "RippleState",
|
|
||||||
"LowLimit" : {
|
|
||||||
"currency" : "USD",
|
|
||||||
"issuer" : "rEuLyBCvcw4CFmzv8RepSiAoNgF8tTGJQC",
|
|
||||||
"value" : "100"
|
|
||||||
},
|
|
||||||
"LowNode" : "0000000000000000",
|
|
||||||
"PreviousTxnID" : "BD636194C48FD7A100DE4C972336534C8E710FD008C0F3CF7BC5BF34DAF3C3E6",
|
|
||||||
"PreviousTxnLgrSeq" : 6,
|
|
||||||
"index" : "93E317B32022977C77810A2C558FBB28E30E744C68E73720622B797F957EC5FA"
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"ledger_hash" : "56E81069F06492FB410A70218C08169BE3AB3CFD5AEA20E999662D81DC361D9F",
|
"ledger_hash" : "56E81069F06492FB410A70218C08169BE3AB3CFD5AEA20E999662D81DC361D9F",
|
||||||
@@ -367,35 +313,50 @@ Connecting to 127.0.0.1:5005
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</code></pre>
|
</code></pre>
|
||||||
<h2 id="7-create-a-new-transaction-that-you-plan-to-multi-sign">7. Create a new transaction that you plan to multi-sign</h2>
|
<p>If the SignerList is present with the expected contents, then your address is ready to multi-sign.</p>
|
||||||
<p>You have to specify <em>everything</em> about this transaction, including <code>Fee</code> and
|
<h3 id="6-further-steps">6. Further steps</h3>
|
||||||
<code>Sequence</code>. Also include the field <code>SigningPubKey</code> as an empty string -- this
|
<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>
|
||||||
indicates that the transaction is multi-signed.</p>
|
<ul>
|
||||||
<p>Here's an example transaction we can send from our test account:</p>
|
<li>Disable the address's master key 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 (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 check that <a href="#availability-of-multi-signing">multi-sign is available</a> and <a href="#set-up-multi-sign">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 (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. Given that it sometimes takes a while to collect signatures from multiple sources, you may want to include additional buffer in case the <a href="concept-transaction-cost.html#load-scaling">transaction cost's load scaling</a> increases in that time.</p>
|
||||||
|
<p>Here's an example transaction ready to be multi-signed:</p>
|
||||||
<pre><code>{
|
<pre><code>{
|
||||||
"TransactionType": "TrustSet",
|
"TransactionType": "TrustSet",
|
||||||
"Account": "rnBFvgZphmN39GWzUJeUitaP22Fr9be75H",
|
"Account": "rEuLyBCvcw4CFmzv8RepSiAoNgF8tTGJQC",
|
||||||
"Flags": 262144,
|
"Flags": 262144,
|
||||||
"LimitAmount": {
|
"LimitAmount": {
|
||||||
"currency": "USD",
|
"currency": "USD",
|
||||||
"issuer": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
"issuer": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
|
||||||
"value": "100"
|
"value": "100"
|
||||||
},
|
},
|
||||||
"Sequence": 2,
|
"Sequence": 2,
|
||||||
"SigningPubKey":"",
|
"SigningPubKey": "",
|
||||||
"Fee": "30000"
|
"Fee": "30000"
|
||||||
}
|
}
|
||||||
</code></pre>
|
</code></pre>
|
||||||
<p>(If you started from a fresh ledger, you first need to fund the account
|
<p>(This transaction creates an accounting relationship from rEuLyBCvcw4CFmzv8RepSiAoNgF8tTGJQC to rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh with a maximum balance of 100 USD.)</p>
|
||||||
specified by the <code>issuer</code> in this example, and then manually close the ledger.)</p>
|
<h3 id="2-get-one-signature">2. Get one signature</h3>
|
||||||
<p>Keep in mind that the <code>Fee</code> for multi-signed transactions is significantly
|
<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>
|
||||||
higher than for regularly-signed transactions. It should be (N+1) times the
|
<p><strong>Caution:</strong> Never submit a secret key to a server you do not control. Do not transmit a secret key unencrypted over the network.</p>
|
||||||
normal fee, where N is the number of signatures you plan to provide. Given that
|
<pre><code>$ rippled sign_for rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW <rsA2L..'s secret> '{
|
||||||
it sometimes takes a while to collect signatures from multiple sources, you may
|
> "TransactionType": "TrustSet",
|
||||||
want to include additional buffer in case the load fee increases in that time.</p>
|
> "Account": "rEuLyBCvcw4CFmzv8RepSiAoNgF8tTGJQC",
|
||||||
<h2 id="8-get-one-signature">8. Get one signature</h2>
|
> "Flags": 262144,
|
||||||
<p>The <a href="reference-rippled.html#sign-for"><code>sign_for</code> command</a> takes an address and related secret, and a transaction in JSON form. It generates a signature for that transaction, using the secret key and address specified. By using this, you can provide signatures that contribute to a multi-signed transaction. (The signatures should come from the members of your SignerList.)</p>
|
> "LimitAmount": {
|
||||||
<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" }'
|
> "currency": "USD",
|
||||||
|
> "issuer": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
|
||||||
|
> "value": "100"
|
||||||
|
> },
|
||||||
|
> "Sequence": 2,
|
||||||
|
> "SigningPubKey": "",
|
||||||
|
> "Fee": "30000"
|
||||||
|
> }'
|
||||||
Loading: "/home/mduo13/.config/ripple/rippled.cfg"
|
Loading: "/home/mduo13/.config/ripple/rippled.cfg"
|
||||||
Connecting to 127.0.0.1:5005
|
Connecting to 127.0.0.1:5005
|
||||||
{
|
{
|
||||||
@@ -428,10 +389,14 @@ Connecting to 127.0.0.1:5005
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</code></pre>
|
</code></pre>
|
||||||
<p>Save the <code>tx_json</code> field of the response: it has the new signature in the <code>Signers</code> field.</p>
|
<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>The <code>tx_blob</code> is not very useful at this point, unless you're "multi-signing" a transaction with only one signature.</p>
|
<h3 id="3-get-additional-signatures">3. Get additional signatures</h3>
|
||||||
<h2 id="9-get-additional-signatures-the-same-way">9. Get additional signatures the same way</h2>
|
<p>You can collect additional signatures in parallel or in serial:</p>
|
||||||
<p>You can collect additional signatures for the same transaction in parallel by using the <code>sign_for</code> command with the same transaction JSON. You can also collect additional signatures in serial: if you provide the <code>tx_json</code> value from a previous <code>sign_for</code> response, the response appends a signature to the existing Signers array.</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><strong>Caution:</strong> Never submit a secret key to a server you do not control. Do not transmit a secret key unencrypted over the network.</p>
|
||||||
<pre><code>$ rippled sign_for rUpy3eEg8rqjqfUoLeBnZkscbKbFsKXC3v <rUpy..'s secret> '{
|
<pre><code>$ rippled sign_for rUpy3eEg8rqjqfUoLeBnZkscbKbFsKXC3v <rUpy..'s secret> '{
|
||||||
> "Account" : "rEuLyBCvcw4CFmzv8RepSiAoNgF8tTGJQC",
|
> "Account" : "rEuLyBCvcw4CFmzv8RepSiAoNgF8tTGJQC",
|
||||||
> "Fee" : "30000",
|
> "Fee" : "30000",
|
||||||
@@ -494,10 +459,10 @@ Connecting to 127.0.0.1:5005
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</code></pre>
|
</code></pre>
|
||||||
<p>Depending on the SignerList you configured, you may need to repeat this step several times in order to get signatures from all the necessary parties.</p>
|
<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>
|
||||||
<h2 id="10-combine-the-signatures-and-submit">10. Combine the signatures and submit</h2>
|
<h3 id="4-combine-signatures-and-submit">4. Combine signatures and submit</h3>
|
||||||
<p>The commandline syntax for the <a href="reference-rippled.html#submit-multisigned"><code>submit_multisigned</code> command</a> takes a single transaction JSON containing a <code>Signers</code> array, so you need to combine all the signatures from the all the responses into a single <code>Signers</code> array field with all the signatures. If you collected signatures serially, the <code>tx_json</code> from the last response is sufficient.</p>
|
<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>The <code>submit_multisigned</code> command actually submits the transaction for inclusion in the ledger. In online mode, this also relays it to other members of the network.</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 '{
|
<pre><code>$ rippled submit_multisigned '{
|
||||||
> "Account" : "rEuLyBCvcw4CFmzv8RepSiAoNgF8tTGJQC",
|
> "Account" : "rEuLyBCvcw4CFmzv8RepSiAoNgF8tTGJQC",
|
||||||
> "Fee" : "30000",
|
> "Fee" : "30000",
|
||||||
@@ -568,9 +533,9 @@ Connecting to 127.0.0.1:5005
|
|||||||
}
|
}
|
||||||
</code></pre>
|
</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>
|
<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>
|
||||||
<h2 id="14-close-the-ledger-one-last-time">14. Close the ledger one last time</h2>
|
<h3 id="5-close-the-ledger">5. Close the ledger</h3>
|
||||||
<p>As before, on the live network, you can wait 4-7 seconds for the ledger to close automatically.</p>
|
<p>If you are using the live network, you can wait 4-7 seconds for the ledger to close automatically.</p>
|
||||||
<p>If 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>
|
<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
|
<pre><code>$ rippled ledger_accept
|
||||||
Loading: "/home/mduo13/.config/ripple/rippled.cfg"
|
Loading: "/home/mduo13/.config/ripple/rippled.cfg"
|
||||||
Connecting to 127.0.0.1:5005
|
Connecting to 127.0.0.1:5005
|
||||||
@@ -581,8 +546,10 @@ Connecting to 127.0.0.1:5005
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</code></pre>
|
</code></pre>
|
||||||
<h2 id="15-confirm-the-results-of-the-transaction">15. Confirm the results of the transaction</h2>
|
<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.</p>
|
<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
|
<pre><code>$ rippled tx BD636194C48FD7A100DE4C972336534C8E710FD008C0F3CF7BC5BF34DAF3C3E6
|
||||||
Loading: "/home/mduo13/.config/ripple/rippled.cfg"
|
Loading: "/home/mduo13/.config/ripple/rippled.cfg"
|
||||||
Connecting to 127.0.0.1:5005
|
Connecting to 127.0.0.1:5005
|
||||||
@@ -694,9 +661,6 @@ Connecting to 127.0.0.1:5005
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</code></pre>
|
</code></pre>
|
||||||
<p>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>
|
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user