diff --git a/concept-reserves.html b/concept-reserves.html index 2bf281ca19..6fa4721fd8 100644 --- a/concept-reserves.html +++ b/concept-reserves.html @@ -146,6 +146,7 @@

Owner Reserve Edge Cases

diff --git a/concept-stand-alone-mode.html b/concept-stand-alone-mode.html index 2a57a14c06..59b79a7637 100644 --- a/concept-stand-alone-mode.html +++ b/concept-stand-alone-mode.html @@ -132,7 +132,7 @@

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 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 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:

Caution: In stand-alone mode, you must manually advance the 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.)

@@ -173,7 +173,7 @@

(TODO: test this)

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 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:

rippled ledger_accept --conf=/path/to/rippled.cfg
 

Advancing Ledgers in Stand-Alone Mode

@@ -181,7 +181,7 @@
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.)

-

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.

diff --git a/content/concept-reserves.md b/content/concept-reserves.md index fee741cc24..9f4297f0c6 100644 --- a/content/concept-reserves.md +++ b/content/concept-reserves.md @@ -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. * [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 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 ## 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. - diff --git a/content/concept-stand-alone-mode.md b/content/concept-stand-alone-mode.md index 654e72ef1b..322ae60602 100644 --- a/content/concept-stand-alone-mode.md +++ b/content/concept-stand-alone-mode.md @@ -1,7 +1,7 @@ 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: @@ -12,7 +12,7 @@ When you run `rippled` in stand-alone mode, you have to tell it what ledger vers 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: @@ -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)) + 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)). @@ -75,7 +76,7 @@ rippled -a --ledger 19860944 --conf=/path/to/rippled.cfg ### 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 @@ -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/).) -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. diff --git a/content/reference-ledger-format.md b/content/reference-ledger-format.md index 686aa968fb..2ad775e176 100644 --- a/content/reference-ledger-format.md +++ b/content/reference-ledger-format.md @@ -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. | | 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 ### 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 ### 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. - diff --git a/content/reference-rippled.md b/content/reference-rippled.md index ccefabb180..bafafb1cd6 100644 --- a/content/reference-rippled.md +++ b/content/reference-rippled.md @@ -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. +## 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 ## [[Source]
](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. +## submit_multisigned ## + +The `submit_multisigned` command takes a transaction specification with multiple signatures and applies that transaction. (TODO: finish this section.) + + + ## book_offers ## [[Source]
](https://github.com/ripple/rippled/blob/develop/src/ripple/rpc/handlers/BookOffers.cpp "Source") diff --git a/content/reference-transaction-format.md b/content/reference-transaction-format.md index 2cb6c4a7fb..d318c47858 100644 --- a/content/reference-transaction-format.md +++ b/content/reference-transaction-format.md @@ -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. -* [Signing and Sending Transactions](#signing-and-sending-transactions) +* [Authorized Transactions](#authorizing-transactions) * [Reliable Transaction Submission](#reliable-transaction-submission) * [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) -## 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 in Ripple is the act of authorizing transactions for the Ripple -Consensus Ledger by using a combination of multiple secret keys. Multi-signing -allows various use cases including: +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. -* If you require keys from different devices, a malicious user must compromise multiple machines in order to send transactions on your behalf. -* 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) +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. +For more information, see [How to Multi-Sign](tutorial-multisign.html). ### Reliable Transaction Submission ### @@ -550,7 +554,7 @@ In rippled's WebSocket and JSON-RPC APIs, the TransferRate is represented as an [[Source]
](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 | |-------|-----------|--------------------------------------------------------|-------------| -| 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 ## [[Source]
](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: @@ -815,14 +821,15 @@ Example SignerListSet: | 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`. | -| 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. 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 # diff --git a/content/tutorial-multisign.md b/content/tutorial-multisign.md index 3182adb01c..84eba1ca5c 100644 --- a/content/tutorial-multisign.md +++ b/content/tutorial-multisign.md @@ -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. -* 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. -* Even more uses than can be described here. +Benefits of multi-signing include: + +* You can require keys from different devices, so that a malicious actor must compromise multiple machines to send transactions on your behalf. +* You can share custody of an address between multiple people, each of whom only has one of several keys necessary to send transactions from that address. +* You can delegate the power to send transactions from your address to a group of people, who can control your address if you are unavailable or unable to sign normally. +* ... and more. + +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 -------------------------------------------------------------------------------- +----------------------------- 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] 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 Loading: "/home/mduo13/.config/ripple/rippled.cfg" Connecting to 127.0.0.1:5005 { - "result" : { - "account_id" : "rEuLyBCvcw4CFmzv8RepSiAoNgF8tTGJQC", - "key_type" : "secp256k1", - "master_key" : "LOST FOUR ALOE ABE SLUG ITS HACK MAGI SOCK BASS APE DELL", - "master_seed" : "sn1CmMEkPijNrfyr8HJqsgP416dr3", - "master_seed_hex" : "E42AD02985BB56923DFC1D002DB510B3", - "public_key" : "aBQgQDutj8YUc7ZRtfj86dnzPCvPcRHtUszxeCCDMgZ7Zq1Thfri", - "public_key_hex" : "03668837C3DCA0F4858587703524E61BB40128B9F6910B80B4655E152CAEE2E321", - "status" : "success" - } + "result" : { + "account_id" : "rnRJ4dpSBKDR2M1itf4Ah6tZZm5xuNZFPH", + "key_type" : "secp256k1", + "master_key" : "FLOG SEND GOES CUFF GAGE FAT ANTI DEL GUM TIRE ISLE BEAR", + "master_seed" : "snheH5UUjU4CWqiNVLny2k21TyKPC", + "master_seed_hex" : "A9F859765EB8614D26809836382AFB82", + "public_key" : "aBR4hxFXcDNHnGYvTiqb2KU8TTTV1cYV9wXTAuz2DjBm7S8TYEBU", + "public_key_hex" : "03C09A5D112B393D531E4F092E3A5769A5752129F0A9C55C61B3A226BB9B567B9B", + "status" : "success" + } } - -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. +Take note of the `account_id` (Ripple Address) and `master_seed` (Ripple secret key) for each one you generate. -## 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. - - $ 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. +[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. 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 '{ > "Flags": 0, > "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 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 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, "SignerQuorum" : 3, "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", @@ -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 -`Sequence`. Also include the field `SigningPubKey` as an empty string -- this -indicates that the transaction is multi-signed. +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. -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", - "Account": "rnBFvgZphmN39GWzUJeUitaP22Fr9be75H", + "Account": "rEuLyBCvcw4CFmzv8RepSiAoNgF8tTGJQC", "Flags": 262144, "LimitAmount": { - "currency": "USD", - "issuer": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", - "value": "100" + "currency": "USD", + "issuer": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", + "value": "100" }, "Sequence": 2, - "SigningPubKey":"", + "SigningPubKey": "", "Fee": "30000" } -(If you started from a fresh ledger, you first need to fund the account -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. +(This transaction creates an accounting relationship from rEuLyBCvcw4CFmzv8RepSiAoNgF8tTGJQC to rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh with a maximum balance of 100 USD.) -## 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 '{ "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 '{ + > "TransactionType": "TrustSet", + > "Account": "rEuLyBCvcw4CFmzv8RepSiAoNgF8tTGJQC", + > "Flags": 262144, + > "LimitAmount": { + > "currency": "USD", + > "issuer": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", + > "value": "100" + > }, + > "Sequence": 2, + > "SigningPubKey": "", + > "Fee": "30000" + > }' Loading: "/home/mduo13/.config/ripple/rippled.cfg" Connecting to 127.0.0.1:5005 { @@ -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. - -The `tx_blob` is not very useful at this point, unless you're "multi-signing" a transaction with only one signature. +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. -## 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 '{ > "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 '{ > "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`.) -## 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 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 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 } } - - -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. diff --git a/reference-ledger-format.html b/reference-ledger-format.html index a8c8207562..ae73cab2e0 100644 --- a/reference-ledger-format.html +++ b/reference-ledger-format.html @@ -1059,6 +1059,7 @@ +

The SignerEntries may be any combination of funded and unfunded addresses that use either secp256k1 or ed25519 keys.

SignerEntry object

Each member of the SignerEntries field is an object that describes that signer in the list. A SignerEntry has the following fields:

diff --git a/reference-rippled.html b/reference-rippled.html index 814a405814..91be30de2d 100644 --- a/reference-rippled.html +++ b/reference-rippled.html @@ -7320,6 +7320,8 @@ rippled sign sssssssssssssssssssssssssssss '{"TransactionType": "Payment", "Acco
  • tooBusy - 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.
  • 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

    [Source]

    The submit method sends a transaction to the network to be confirmed and included in future ledgers.

    @@ -7588,6 +7590,8 @@ submit sssssssssssssssssssssssssssss '{"TransactionType":"Payment", "Account":"r
  • internalSubmit - 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.
  • 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

    [Source]

    The book_offers method retrieves a list of offers, also known as the order book, 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.

    diff --git a/reference-transaction-format.html b/reference-transaction-format.html index 0d5b611f51..46928e135b 100644 --- a/reference-transaction-format.html +++ b/reference-transaction-format.html @@ -147,15 +147,36 @@

    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 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.

    -

    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 for details.) If your account has a SignerList associated with it, you can use a multi-signature instead.

    -

    Typically, you create a transaction in JSON format first. Here is an example of an unsigned Payment-type transaction in JSON:

    +

    Authorizing Transactions

    +

    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.

    +

    A transaction can be authorized by any of the following types of signatures:

    +
      +
    • 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.
    • +
    • 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.
    • +
    • A multi-signature that matches a list of signers enabled for the address. You can enable, remove, or replace a list of signers using a SignerListSet transaction.
    • +
    +

    Any signature type can authorize any type of transaction, with the following exceptions:

    + +

    Signing and Submitting Transactions

    +

    Sending a transaction to the Ripple Consensus Ledger involves several steps:

    +
      +
    1. Create an unsigned transaction in JSON format.
    2. +
    3. Use one or more signatures to authorize the transaction.
    4. +
    5. 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.
    6. +
    7. The consensus process determines which provisional transactions get included in the next validated ledger.
    8. +
    9. The rippled servers apply those transactions to the previous ledger in a canonical order and share their results.
    10. +
    11. If enough trusted validators created the exact same ledger, that ledger is declared validated and the results of the transactions in that ledger are immutable.
    12. +
    +

    Here is an example of an unsigned Payment-type transaction in JSON:

    {
       "TransactionType" : "Payment",
       "Account" : "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
    @@ -276,28 +297,9 @@
     }
     

    Multi-Signing

    -

    Multi-signing in Ripple is the act of authorizing transactions for the Ripple -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.
    • -
    • 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 to define which accounts or keys can, together, authorize transactions for this account.
    2. -
    3. Optionally disable the master key with an AccountSet transaction using the asfDisableMaster flag.
    4. -
    5. Optionally remove the existing regular key (if any) with a SetRegularKey transaction.
    6. -
    -

    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. -
    3. Generate a signature for each account using the sign_for command.
    4. -
    5. Combine the signatures and submit using the submit_multisigned command.
    6. -
    -

    Main article: 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. Multi-signing is due to be enabled by an Amendment to the Ripple Consensus Protocol. You can use multi-signing in addition to, or instead of, a master key, a regular key, or both.

    +

    The SignerListSet transaction 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.

    +

    For more information, see How to Multi-Sign.

    Reliable Transaction Submission

    Reliably submitting transactions is the process of achieving both of the following:

      @@ -883,7 +885,7 @@ allows various use cases including:

      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 1200000000. 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.

      SetRegularKey

      [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.

      {
           "Flags": 0,
           "TransactionType": "SetRegularKey",
      @@ -905,14 +907,15 @@ allows various use cases including:

    - - + +
    RegularKey StringAccount(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.AccountID(Optional) A base-58-encoded Ripple address 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 or the master key.

    -

    A Regular Key pair is generated in the same way as any other Ripple keys (for example, with 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 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, but multi-signing costs additional XRP in transaction fees and reserves.

    -

    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 without paying the transaction cost.

    +

    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.

    +

    A regular key pair is generated in the same way as any other Ripple keys (for example, with 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 a master key but you cannot change it.

    +

    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 without paying the transaction cost.

    +

    For even greater security, you can use multi-signing, but multi-signing requires additional XRP for the transaction cost and reserve.

    OfferCreate

    [Source]

    An OfferCreate transaction is effectively a limit order. 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.

    @@ -1202,7 +1205,7 @@ allows various use cases including:

    SignerListSet

    [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 a transaction.

    Example SignerListSet:

    {
         "Flags": 0,
    @@ -1252,13 +1255,14 @@ allows various use cases including:

    SignerEntries Array Array -(Omitted when deleting) Array of SignerEntry objects, 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. +(Omitted when deleting) Array of SignerEntry objects, 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. 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.

    -

    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 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.

    +

    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 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.

    Pseudo-Transactions

    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.

    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:

    diff --git a/tutorial-multisign.html b/tutorial-multisign.html index 19e760bae1..572b70e63f 100644 --- a/tutorial-multisign.html +++ b/tutorial-multisign.html @@ -126,92 +126,60 @@
    -

    Introduction to Multi-Signing

    -

    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.

    +

    How to Multi-Sign

    +

    Multi-signing is one of three ways to authorize transactions for the Ripple Consensus Ledger, alongside signing with regular keys and master keys. You can configure your address to allow any combination of the three methods to authorize transactions.

    +

    Benefits of multi-signing include:

      -
    • 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.
    • -
    • 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.
    • -
    • Even more uses than can be described here.
    • +
    • You can require keys from different devices, so that a malicious actor must compromise multiple machines to send transactions on your behalf.
    • +
    • You can share custody of an address between multiple people, each of whom only has one of several keys necessary to send transactions from that address.
    • +
    • You can delegate the power to send transactions from your address to a group of people, who can control your address if you are unavailable or unable to sign normally.
    • +
    • ... and more.
    +

    To use multi-signing:

    +
      +
    1. The Ripple peer-to-peer network must have multi-signing enabled.
    2. +
    3. Set up a list of signers on your account.
    4. +
    5. Send transactions using multiple signatures.
    6. +

    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.

    -

    You can test multi-signing by running rippled in stand-alone mode 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 with the MultiSign feature enabled. To enable multi-signing for testing, add the following stanza to your rippled.cfg:

    [features]
     MultiSign
     
    -

    How to Multi-Sign

    -

    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.

    -

    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.

    +

    Setting up Multi-Signing

    +

    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. The following procedure demonstrates how to set up a SignerList for your address:

    +

    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 and transaction cost, increasing with the number of signers and signatures you use.

    +

    If you started rippled in stand-alone mode with a new genesis ledger, you must:

    +
      +
    1. Generate keys for a new address, or reuse keys you already have.
    2. +
    3. Submit a Payment transaction to fund the new address from the genesis account. (Send at least 100,000,000 drops of XRP.)
    4. +
    5. Manually close the ledger.
    6. +
    +

    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. For example:

    $ rippled wallet_propose
     Loading: "/home/mduo13/.config/ripple/rippled.cfg"
     Connecting to 127.0.0.1:5005
     {
    -   "result" : {
    -      "account_id" : "rEuLyBCvcw4CFmzv8RepSiAoNgF8tTGJQC",
    -      "key_type" : "secp256k1",
    -      "master_key" : "LOST FOUR ALOE ABE SLUG ITS HACK MAGI SOCK BASS APE DELL",
    -      "master_seed" : "sn1CmMEkPijNrfyr8HJqsgP416dr3",
    -      "master_seed_hex" : "E42AD02985BB56923DFC1D002DB510B3",
    -      "public_key" : "aBQgQDutj8YUc7ZRtfj86dnzPCvPcRHtUszxeCCDMgZ7Zq1Thfri",
    -      "public_key_hex" : "03668837C3DCA0F4858587703524E61BB40128B9F6910B80B4655E152CAEE2E321",
    -      "status" : "success"
    -   }
    +    "result" : {
    +        "account_id" : "rnRJ4dpSBKDR2M1itf4Ah6tZZm5xuNZFPH",
    +        "key_type" : "secp256k1",
    +        "master_key" : "FLOG SEND GOES CUFF GAGE FAT ANTI DEL GUM TIRE ISLE BEAR",
    +        "master_seed" : "snheH5UUjU4CWqiNVLny2k21TyKPC",
    +        "master_seed_hex" : "A9F859765EB8614D26809836382AFB82",
    +        "public_key" : "aBR4hxFXcDNHnGYvTiqb2KU8TTTV1cYV9wXTAuz2DjBm7S8TYEBU",
    +        "public_key_hex" : "03C09A5D112B393D531E4F092E3A5769A5752129F0A9C55C61B3A226BB9B567B9B",
    +        "status" : "success"
    +    }
     }
     
    -

    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

    -

    Again, this step is only necessary if you are setting up a new account to use multi-signing for this example.

    -
    $ 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.

    -
    $ 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.

    -

    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.

    +

    Take note of the account_id (Ripple Address) and master_seed (Ripple secret key) for each one you generate.

    +

    3. Send SignerListSet transaction

    +

    Sign and submit a SignerListSet transaction 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.

    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 '{
     >     "Flags": 0,
     >     "TransactionType": "SignerListSet",
    @@ -282,10 +250,11 @@ Connecting to 127.0.0.1:5005
        }
     }
     
    -

    Make sure that the engine_result value in the response is tesSUCCESS. Otherwise, the transaction failed.

    -

    5. Close the ledger again

    -

    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 to manually close the ledger:

    +

    Make sure that the Transaction Result is tesSUCCESS. Otherwise, the transaction failed.

    +

    Note: The more members in the SignerList, the more XRP your address must have for purposes of the owner reserve. If your address does not have enough XRP, the transaction fails with tecINSUFFICIENT_RESERVE. See also: SignerLists and Reserves.

    +

    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 to manually close the ledger:

    $ rippled ledger_accept
     Loading: "/home/mduo13/.config/ripple/rippled.cfg"
     Connecting to 127.0.0.1:5005
    @@ -296,8 +265,9 @@ Connecting to 127.0.0.1:5005
        }
     }
     
    -

    6. Confirm the presence of the new signer list using account_objects

    -

    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.

    +

    5. Confirm the new signer list

    +

    Use the account_objects command 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
     Loading: "/home/mduo13/.config/ripple/rippled.cfg"
     Connecting to 127.0.0.1:5005
    @@ -334,30 +304,6 @@ Connecting to 127.0.0.1:5005
                 "SignerListID" : 0,
                 "SignerQuorum" : 3,
                 "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",
    @@ -367,35 +313,50 @@ Connecting to 127.0.0.1:5005
        }
     }
     
    -

    7. Create a new transaction that you plan to multi-sign

    -

    You have to specify everything about this transaction, including Fee and -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:

    +

    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. You may also want to:

    + +

    Sending a Multi-Signed Transaction

    +

    Before you can multi-sign a transaction, first check that multi-sign is available and set up multi-signing for your address. The following procedure demonstrates how to create, sign, and submit a multi-signed transaction.

    +

    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, 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 increases in that time.

    +

    Here's an example transaction ready to be multi-signed:

    {
         "TransactionType": "TrustSet",
    -    "Account": "rnBFvgZphmN39GWzUJeUitaP22Fr9be75H",
    +    "Account": "rEuLyBCvcw4CFmzv8RepSiAoNgF8tTGJQC",
         "Flags": 262144,
         "LimitAmount": {
    -      "currency": "USD",
    -      "issuer": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
    -      "value": "100"
    +        "currency": "USD",
    +        "issuer": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
    +        "value": "100"
         },
         "Sequence": 2,
    -    "SigningPubKey":"",
    +    "SigningPubKey": "",
         "Fee": "30000"
     }
     
    -

    (If you started from a fresh ledger, you first need to fund the account -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

    -

    The sign_for command 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.)

    -
    $ 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" }'
    +

    (This transaction creates an accounting relationship from rEuLyBCvcw4CFmzv8RepSiAoNgF8tTGJQC to rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh with a maximum balance of 100 USD.)

    +

    2. Get one signature

    +

    Use the sign_for command with the secret key and address of one of the members of your SignerList to get a signature for that member.

    +

    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"
     Connecting to 127.0.0.1:5005
     {
    @@ -428,10 +389,14 @@ Connecting to 127.0.0.1:5005
        }
     }
     
    -

    Save the tx_json field of the response: it has the new signature in the Signers 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

    -

    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.

    +

    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.

    +

    3. Get additional signatures

    +

    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> '{
     >    "Account" : "rEuLyBCvcw4CFmzv8RepSiAoNgF8tTGJQC",
     >    "Fee" : "30000",
    @@ -494,10 +459,10 @@ Connecting to 127.0.0.1:5005
        }
     }
     
    -

    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.

    -

    10. Combine the signatures and submit

    -

    The commandline syntax for the submit_multisigned command 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.

    -

    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.

    +

    Depending on the SignerList you configured, you may need to repeat this step several times to get signatures from all the necessary parties.

    +

    4. Combine signatures and submit

    +

    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.

    +

    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.

    $ rippled submit_multisigned '{
     >              "Account" : "rEuLyBCvcw4CFmzv8RepSiAoNgF8tTGJQC",
     >              "Fee" : "30000",
    @@ -568,9 +533,9 @@ Connecting to 127.0.0.1:5005
     }
     

    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

    -

    As before, on 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 to manually close the ledger:

    +

    5. Close the ledger

    +

    If you are using 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 to manually close the ledger:

    $ rippled ledger_accept
     Loading: "/home/mduo13/.config/ripple/rippled.cfg"
     Connecting to 127.0.0.1:5005
    @@ -581,8 +546,10 @@ Connecting to 127.0.0.1:5005
        }
     }
     
    -

    15. Confirm the results of the transaction

    -

    Use the hash value from the response to the submit_multisigned command.

    +

    6. Confirm transaction results

    +

    Use the hash value from the response to the submit_multisigned command to look up the transaction using the tx command. 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
     Loading: "/home/mduo13/.config/ripple/rippled.cfg"
     Connecting to 127.0.0.1:5005
    @@ -694,9 +661,6 @@ Connecting to 127.0.0.1:5005
         }
     }
     
    -

    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.