mirror of
https://github.com/XRPLF/xrpl-dev-portal.git
synced 2025-11-20 19:55:54 +00:00
798 lines
38 KiB
HTML
798 lines
38 KiB
HTML
<!DOCTYPE html>
|
|
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta content="IE=edge,chrome=1" http-equiv="X-UA-Compatible">
|
|
<meta content="width=device-width" name="viewport">
|
|
<title>Multi-Signing Transactions - Ripple Developer Portal</title>
|
|
<!-- favicon -->
|
|
<link href="favicon.ico" rel="icon" type="image/x-icon">
|
|
<link href="favicon.ico" rel="shortcut icon" type="image/x-icon">
|
|
<!-- jQuery -->
|
|
<script src="assets/vendor/jquery-1.11.1.min.js"></script>
|
|
<!-- Custom Stylesheets. ripple.css includes bootstrap, font stuff -->
|
|
<link href="assets/css/ripple.css" rel="stylesheet"/>
|
|
<link href="assets/css/devportal.css" rel="stylesheet"/>
|
|
<!-- Bootstrap JS -->
|
|
<script src="assets/vendor/bootstrap.min.js"></script>
|
|
<!-- syntax highlighting -->
|
|
<link href="assets/vendor/docco.min.css" rel="stylesheet">
|
|
<script src="assets/vendor/highlight.min.js"></script>
|
|
<!-- syntax selection js -->
|
|
<script src="assets/js/multicodetab.js"></script>
|
|
<script>
|
|
$(document).ready(function() {
|
|
$().multicode_tabs();
|
|
hljs.initHighlighting();
|
|
make_code_expandable();
|
|
});
|
|
</script>
|
|
<script src="assets/js/expandcode.js"></script>
|
|
<script src="assets/js/fixsidebarscroll.js"></script>
|
|
</link></link></link></meta></meta></meta></head>
|
|
<body class="page page-template page-template-template-dev-portal page-template-template-dev-portal-php sidebar-primary wpb-js-composer js-comp-ver-3.6.2 vc_responsive">
|
|
<header class="banner navbar navbar-default navbar-fixed-top initial_header" role="banner">
|
|
<div class="container">
|
|
<div class="navbar-header">
|
|
<a class="navbar-brand" href="index.html"><img class="logo" src="assets/img/ripple-logo-color.png"/></a>
|
|
</div><!-- /.navbar-header -->
|
|
<div class="nav">
|
|
<div class="draft-warning">DRAFT PAGE</div>
|
|
</div><!-- /.nav -->
|
|
</div><!-- /.container -->
|
|
<div class="subnav dev_nav">
|
|
<div class="container">
|
|
<ul class="menu" id="menu-dev-menu">
|
|
<li class="dropdown">
|
|
<a class="dropdown-toggle" data-toggle="dropdown" href="#">References <span class="caret"></span></a>
|
|
<ul class="dropdown-menu" role="menu">
|
|
<li><a href="reference-rippled.html">rippled</a></li>
|
|
<li><a href="reference-transaction-format.html">Transaction Format</a></li>
|
|
<li><a href="reference-ledger-format.html">Ledger Format</a></li>
|
|
<li><a href="reference-rippleapi.html">RippleAPI</a></li>
|
|
<li><a href="reference-data-api.html">Ripple Data API v2</a></li>
|
|
</ul>
|
|
</li>
|
|
<li class="dropdown">
|
|
<a class="dropdown-toggle" data-toggle="dropdown" href="#">Tutorials <span class="caret"></span></a>
|
|
<ul class="dropdown-menu" role="menu">
|
|
<li><a href="tutorial-rippleapi-beginners-guide.html">RippleAPI Beginners Guide</a></li>
|
|
<li><a href="tutorial-rippled-setup.html">rippled Setup</a></li>
|
|
<li><a href="tutorial-reliable-transaction-submission.html">Reliable Transaction Submission</a></li>
|
|
<li><a href="tutorial-multisign.html">Multi-Signing Transactions</a></li>
|
|
</ul>
|
|
</li>
|
|
<li class="dropdown">
|
|
<a class="dropdown-toggle" data-toggle="dropdown" href="#">Concepts <span class="caret"></span></a>
|
|
<ul class="dropdown-menu" role="menu">
|
|
<li><a href="concept-paths.html">Paths</a></li>
|
|
<li><a href="concept-fees.html">Fees (Disambiguation)</a></li>
|
|
<li><a href="concept-transfer-fees.html">Transfer Fees</a></li>
|
|
<li><a href="concept-transaction-cost.html">Transaction Cost</a></li>
|
|
<li><a href="concept-fee-voting.html">Fee Voting</a></li>
|
|
<li><a href="concept-reserves.html">Reserves</a></li>
|
|
<li><a href="concept-freeze.html">Freeze</a></li>
|
|
</ul>
|
|
</li>
|
|
<li class="dropdown">
|
|
<a class="dropdown-toggle" data-toggle="dropdown" href="#">Best Practices <span class="caret"></span></a>
|
|
<ul class="dropdown-menu" role="menu">
|
|
<li><a href="concept-issuing-and-operational-addresses.html">Issuing and Operational Addresses</a></li>
|
|
<li><a href="tutorial-gateway-guide.html">Gateway Guide</a></li>
|
|
</ul>
|
|
</li>
|
|
<li class="dropdown">
|
|
<a class="dropdown-toggle" data-toggle="dropdown" href="#">API Tools <span class="caret"></span></a>
|
|
<ul class="dropdown-menu" role="menu">
|
|
<li><a href="ripple-api-tool.html">WebSocket API Tool</a></li>
|
|
<li><a href="data-api-v2-tool.html">Data API v2 Tool</a></li>
|
|
<li><a href="tool-jsonrpc.html">rippled JSON-RPC Tool</a></li>
|
|
</ul>
|
|
</li>
|
|
<li class="dropdown">
|
|
<a class="dropdown-toggle" data-toggle="dropdown" href="#">Resources <span class="caret"></span></a>
|
|
<ul class="dropdown-menu" role="menu">
|
|
<li><a href="https://forum.ripple.com/viewforum.php?f=2">Forums</a></li>
|
|
<li><a href="https://www.bountysource.com/teams/ripple/bounties">Bounties</a></li>
|
|
<li><a href="https://ripplelabs.atlassian.net/">Bug Tracking</a></li>
|
|
<li><a href="https://ripple.com/category/dev-blog/">Dev Blog</a></li>
|
|
<li><a href="https://ripple.com/press-releases/">Press Center</a></li>
|
|
<li><a href="https://ripple.com/brand-guidelines/">Brand Guidelines</a></li>
|
|
</ul>
|
|
<li><a href="https://github.com/ripple/ripple-dev-portal" title="GitHub">Site Source</a></li>
|
|
</li></ul><!-- /#dev-menu -->
|
|
</div><!-- /.subnav .container -->
|
|
</div><!-- /.subnav -->
|
|
</header>
|
|
<div class="wrap container" role="document">
|
|
<aside class="sidebar" role="complementary">
|
|
<div class="dev_nav_wrapper">
|
|
<div id="cont">
|
|
<ul class="dev_nav_sidebar">
|
|
<li class="level-1"><a href="index.html">Category: Tutorials</a></li>
|
|
<li class="level-2"><a href="tutorial-rippleapi-beginners-guide.html">RippleAPI Beginners Guide</a></li>
|
|
<li class="level-2"><a href="tutorial-rippled-setup.html">rippled Setup</a></li>
|
|
<li class="level-2"><a href="tutorial-reliable-transaction-submission.html">Reliable Transaction Submission</a></li>
|
|
<li class="level-2"><a href="tutorial-multisign.html">Multi-Signing Transactions</a></li>
|
|
</ul>
|
|
<hr/>
|
|
<h5>In this page:</h5>
|
|
</div>
|
|
<script src="assets/js/jquery.gensidebar.js" type="text/javascript"></script>
|
|
</div>
|
|
</aside>
|
|
<main class="main" role="main">
|
|
<div class="content">
|
|
<h1 id="introduction-to-multi-signing">Introduction to Multi-Signing</h1>
|
|
<p>Multi-signing in Ripple is the act of authorizing transactions for the Ripple
|
|
Consensus Ledger by using a combination of multiple secret keys. After setting
|
|
up multi-signing for an account, you can put the master secret in cold storage,
|
|
or even disable the master key entirely. With multiple secret keys required to
|
|
authorize a multi-signature, you can improve security in several ways.</p>
|
|
<ul>
|
|
<li>If you keep an account's keys on different devices, a malicious user must compromise multiple machines in order to send transactions on your behalf.</li>
|
|
<li>If the keys to an account are in the custody of entirely different people, those people must collaborate in order to send transaction from that account.</li>
|
|
<li>You can use the SignerList as a backup, to delegate a group of others who can send transactions for you if you are unavailable or unable to sign using your regular key.</li>
|
|
<li>Even more uses than can be described here.</li>
|
|
</ul>
|
|
<h2 id="availability-of-multi-signing">Availability of Multi-Signing</h2>
|
|
<p>Multi-signing is due to be enabled by an <strong>Amendment</strong> to the Ripple Consensus
|
|
Protocol. This Amendment must be approved by a consensus of validators showing
|
|
consistent support for the feature over a period of time. For more information,
|
|
see Amendments (TODO: link).</p>
|
|
<p>You can test multi-signing by running <code>rippled</code> in stand-alone mode with the
|
|
feature enabled. In stand-alone mode, <code>rippled</code> does not communicate with the
|
|
rest of the Ripple peer-to-peer network, but you can perform most of the same
|
|
actions on your local server only. This way, you can be sure that you are ready
|
|
for multi-signing when it goes live.</p>
|
|
<h1 id="how-to-multi-sign">How to Multi-Sign</h1>
|
|
<p>The basic process of Multi-Signing a transaction is necessarily more
|
|
complex than the process of signing a transaction with a single master key or
|
|
regular key. </p>
|
|
<h2 id="1-download-and-build-rippled-with-multi-sign">1. Download and build rippled with multi-sign</h2>
|
|
<p>Until a binary for <code>rippled</code> with multi-signing is available, the best you can do is build it from source.</p>
|
|
<pre><code>$ git clone git@github.com:scottschurr/rippled.git (TODO: switch to a Ripple Labs repo when available)
|
|
$ git checkout fix-sign_for
|
|
$ scons
|
|
</code></pre>
|
|
<p>See <a href="https://wiki.ripple.com/Rippled_build_instructions">rippled build instructions</a> for help building from source.</p>
|
|
<h2 id="2-configure-rippled-to-enable-multisign">2. Configure rippled to enable MultiSign</h2>
|
|
<p>Add the following to the bottom of the config file:</p>
|
|
<pre><code>[features]
|
|
MultiSign
|
|
</code></pre>
|
|
<p>Note that this stanza is case-sensitive.</p>
|
|
<h2 id="3-start-rippled-in-stand-alone-mode">3. Start rippled in stand-alone mode</h2>
|
|
<p>If you have previously synced to the network, you can have the server load the
|
|
latest ledger as a starting place for stand-alone mode using the <code>--load</code>
|
|
commandline option:</p>
|
|
<pre><code>$ sudo ./build/rippled --conf=/home/mduo13/.config/ripple/rippled.cfg -a --load
|
|
</code></pre>
|
|
<p>If you'd rather start from scratch, you can use the <code>--start</code> commandline
|
|
option to create a fresh ledger. In this case, the root account holds all
|
|
100 billion XRP:</p>
|
|
<p><strong>Address:</strong> <code>rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh</code></p>
|
|
<p><strong>Secret:</strong> <code>snoPBrXtMeMyMHUVTgbuqAfg1SUTb</code> ("masterpassphrase")</p>
|
|
<h2 id="4-generate-keys-for-a-new-wallet">4. Generate keys for a new wallet</h2>
|
|
<p>This step is not strictly necessary. For this process, we generate the keys to
|
|
a new Ripple account and then set up multi-signing for that account. To set up
|
|
multi-signing on an existing Ripple account, just use the keys to that account.</p>
|
|
<pre><code>$ build/rippled wallet_propose
|
|
Loading: "/home/mduo13/.config/ripple/rippled.cfg"
|
|
Connecting to 127.0.0.1:5005
|
|
{
|
|
"result" : {
|
|
"account_id" : "rnBFvgZphmN39GWzUJeUitaP22Fr9be75H",
|
|
"key_type" : "secp256k1",
|
|
"master_key" : "NED MANA SPA BLUR HERS HEAT RED NIBS MAIN MELT NOB RARE",
|
|
"master_seed" : "shqZZy2Rzs9ZqWTCQAdqc3bKgxnYq",
|
|
"master_seed_hex" : "99C7F2DCD88218372B7509ADF7DC562B",
|
|
"public_key" : "aBPvx491i2ZPVzmxoAmAVq5qXAxAZgmjfxoMTxFCg9Xxf2xwVVLc",
|
|
"public_key_hex" : "0303E20EC6B4A39A629815AE02C0A1393B9225E3B890CAE45B59F42FA29BE9668D",
|
|
"status" : "success"
|
|
}
|
|
}
|
|
</code></pre>
|
|
<p>As always, be sure that an account's secret key never gets transmitted to
|
|
anyone you don't trust with full control of that account, and certainly not
|
|
unencrypted over the network.</p>
|
|
<h2 id="5-fund-the-new-account-with-an-existing-wallet">5. Fund the new account with an existing wallet</h2>
|
|
<p>Again, this step is only necessary if you are setting up a new account to use
|
|
multi-signing for this example.</p>
|
|
<pre><code>$ build/rippled submit <your existing account secret> '{
|
|
> "TransactionType" : "Payment",
|
|
> "Account" : "<your existing account address>",
|
|
> "Destination" : "rnBFvgZphmN39GWzUJeUitaP22Fr9be75H",
|
|
> "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" : "1200002280000000240000001E614000000005F5E10068400000000000000A7321023693F15967AE357D0327974AD46FE3C127113B1110D6044FD41E723689F81CC67446304402207AB5D16F58E9E6ADBBDD24837CAB80D871860E47EB0840FE57403FB979755A6D022015FE7A8838BEE6C18962C246D6D27791B7EE34B93415AE3824D12564E7A886C6811493B89AFCAD4C8EAC2B131C1331FEF12AE1522BBE83142DECAB42CA805119A9BA2FF305C9AFA12F0B86A1",
|
|
"tx_json" : {
|
|
"Account" : "rN7n7otQDd6FczFgLdSqtcsAUxDkw6fzRH",
|
|
"Amount" : "100000000",
|
|
"Destination" : "rnBFvgZphmN39GWzUJeUitaP22Fr9be75H",
|
|
"Fee" : "10",
|
|
"Flags" : 2147483648,
|
|
"Sequence" : 30,
|
|
"SigningPubKey" : "023693F15967AE357D0327974AD46FE3C127113B1110D6044FD41E723689F81CC6",
|
|
"TransactionType" : "Payment",
|
|
"TxnSignature" : "304402207AB5D16F58E9E6ADBBDD24837CAB80D871860E47EB0840FE57403FB979755A6D022015FE7A8838BEE6C18962C246D6D27791B7EE34B93415AE3824D12564E7A886C6",
|
|
"hash" : "8C7A4D35D71CE80DA4EDAC91D620B6A348B7691B78AA2896284135378E10E0C2"
|
|
}
|
|
}
|
|
}
|
|
</code></pre>
|
|
<h2 id="6-manually-close-the-ledger">6. Manually close the ledger</h2>
|
|
<p>In the live network, you would simply wait for the ledger to close
|
|
automatically as the result of consensus. However, a rippled node running in
|
|
stand-alone mode does not engage in consensus, so you must manually close the
|
|
ledger with the <a href="rippled-apis.html#ledger-accept"><code>ledger_accept</code> command</a>.</p>
|
|
<pre><code>$ build/rippled ledger_accept
|
|
Loading: "/home/mduo13/.config/ripple/rippled.cfg"
|
|
Connecting to 127.0.0.1:5005
|
|
{
|
|
"result" : {
|
|
"ledger_current_index" : 16061437,
|
|
"status" : "success"
|
|
}
|
|
}
|
|
</code></pre>
|
|
<h2 id="7-create-a-signerlist-on-the-new-account-with-a-signerlistset-transaction">7. Create a SignerList on the new account with a SignerListSet transaction</h2>
|
|
<p>Before you can multi-sign transactions, you must associate a SignerList with
|
|
your account, so that RCL knows which keys can be used to sign for you. You do
|
|
this with a <a href="transactions.html#signerlistset">SignerListSet transaction</a>.</p>
|
|
<p>In this example, the SignerList has 3 members, with the weights and quorum set
|
|
up such that multi-signed transactions need a signature from
|
|
rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW plus at least one signature from the other
|
|
two members of the list. The <code>Account</code> values you use in your list can be
|
|
funded accounts that exist in the ledger or just unused addresses.</p>
|
|
<pre><code>$ build/rippled submit shqZZy2Rzs9ZqWTCQAdqc3bKgxnYq '{
|
|
> "Flags": 0,
|
|
> "TransactionType": "SignerListSet",
|
|
> "Account": "rnBFvgZphmN39GWzUJeUitaP22Fr9be75H",
|
|
> "Fee": "10000",
|
|
> "SignerQuorum": 3,
|
|
> "SignerEntries": [
|
|
> {
|
|
> "SignerEntry": {
|
|
> "Account": "rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW",
|
|
> "SignerWeight": 2
|
|
> }
|
|
> },
|
|
> {
|
|
> "SignerEntry": {
|
|
> "Account": "rUpy3eEg8rqjqfUoLeBnZkscbKbFsKXC3v",
|
|
> "SignerWeight": 1
|
|
> }
|
|
> },
|
|
> {
|
|
> "SignerEntry": {
|
|
> "Account": "raKEEVSGnKSD9Zyvxu4z6Pqpm4ABH8FS6n",
|
|
> "SignerWeight": 1
|
|
> }
|
|
> }
|
|
> ]
|
|
> }'
|
|
Loading: "/home/mduo13/.config/ripple/rippled.cfg"
|
|
Connecting to 127.0.0.1:5005
|
|
{
|
|
"result" : {
|
|
"engine_result" : "tesSUCCESS",
|
|
"engine_result_code" : 0,
|
|
"engine_result_message" : "The transaction was applied. Only final in a validated ledger.",
|
|
"status" : "success",
|
|
"tx_blob" : "12000C2200000000240000000120230000000368400000000000271073210303E20EC6B4A39A629815AE02C0A1393B9225E3B890CAE45B59F42FA29BE9668D74473045022100BEDFA12502C66DDCB64521972E5356F4DB965F553853D53D4C69B4897F11B4780220595202D1E080345B65BAF8EBD6CA161C227F1B62C7E72EA5CA282B9434A6F04281142DECAB42CA805119A9BA2FF305C9AFA12F0B86A1F4EB1300028114204288D2E47F8EF6C99BCC457966320D12409711E1EB13000181147908A7F0EDD48EA896C3580A399F0EE78611C8E3E1EB13000181143A4C02EA95AD6AC3BED92FA036E0BBFB712C030CE1F1",
|
|
"tx_json" : {
|
|
"Account" : "rnBFvgZphmN39GWzUJeUitaP22Fr9be75H",
|
|
"Fee" : "10000",
|
|
"Flags" : 0,
|
|
"Sequence" : 1,
|
|
"SignerEntries" : [
|
|
{
|
|
"SignerEntry" : {
|
|
"Account" : "rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW",
|
|
"SignerWeight" : 2
|
|
}
|
|
},
|
|
{
|
|
"SignerEntry" : {
|
|
"Account" : "rUpy3eEg8rqjqfUoLeBnZkscbKbFsKXC3v",
|
|
"SignerWeight" : 1
|
|
}
|
|
},
|
|
{
|
|
"SignerEntry" : {
|
|
"Account" : "raKEEVSGnKSD9Zyvxu4z6Pqpm4ABH8FS6n",
|
|
"SignerWeight" : 1
|
|
}
|
|
}
|
|
],
|
|
"SignerQuorum" : 3,
|
|
"SigningPubKey" : "0303E20EC6B4A39A629815AE02C0A1393B9225E3B890CAE45B59F42FA29BE9668D",
|
|
"TransactionType" : "SignerListSet",
|
|
"TxnSignature" : "3045022100BEDFA12502C66DDCB64521972E5356F4DB965F553853D53D4C69B4897F11B4780220595202D1E080345B65BAF8EBD6CA161C227F1B62C7E72EA5CA282B9434A6F042",
|
|
"hash" : "3950D98AD20DA52EBB1F3937EF32F382D74092A4C8DF9A0B1A06ED25200B5756"
|
|
}
|
|
}
|
|
}
|
|
</code></pre>
|
|
<h2 id="8-manually-close-the-ledger-again">8. Manually close the ledger again</h2>
|
|
<p>As before, you would wait for the ledger to close on a live network. We use
|
|
the <a href="rippled-apis.html#ledger-accept"><code>ledger_accept</code> command</a> to manually
|
|
close the ledger when running <code>rippled</code> in stand-alone mode.</p>
|
|
<pre><code>$ build/rippled ledger_accept
|
|
Loading: "/home/mduo13/.config/ripple/rippled.cfg"
|
|
Connecting to 127.0.0.1:5005
|
|
{
|
|
"result" : {
|
|
"ledger_current_index" : 16061438,
|
|
"status" : "success"
|
|
}
|
|
}
|
|
</code></pre>
|
|
<h2 id="9-confirm-the-presence-of-the-new-signer-list-using-account-objects">9. Confirm the presence of the new signer list using account_objects</h2>
|
|
<p>Normally an account has lots of different types of objects, but for this new
|
|
account, the only thing we've done is add a SignerList, so it should be easy to
|
|
find in the results of the
|
|
<a href="rippled-apis.html#account-objects"><code>account_objects</code> command</a>.</p>
|
|
<pre><code>$ build/rippled account_objects rnBFvgZphmN39GWzUJeUitaP22Fr9be75H
|
|
Loading: "/home/mduo13/.config/ripple/rippled.cfg"
|
|
Connecting to 127.0.0.1:5005
|
|
{
|
|
"result" : {
|
|
"account" : "rnBFvgZphmN39GWzUJeUitaP22Fr9be75H",
|
|
"account_objects" : [
|
|
{
|
|
"Flags" : 0,
|
|
"LedgerEntryType" : "SignerList",
|
|
"OwnerNode" : "0000000000000000",
|
|
"PreviousTxnID" : "3950D98AD20DA52EBB1F3937EF32F382D74092A4C8DF9A0B1A06ED25200B5756",
|
|
"PreviousTxnLgrSeq" : 16061437,
|
|
"SignerEntries" : [
|
|
{
|
|
"SignerEntry" : {
|
|
"Account" : "rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW",
|
|
"SignerWeight" : 2
|
|
}
|
|
},
|
|
{
|
|
"SignerEntry" : {
|
|
"Account" : "raKEEVSGnKSD9Zyvxu4z6Pqpm4ABH8FS6n",
|
|
"SignerWeight" : 1
|
|
}
|
|
},
|
|
{
|
|
"SignerEntry" : {
|
|
"Account" : "rUpy3eEg8rqjqfUoLeBnZkscbKbFsKXC3v",
|
|
"SignerWeight" : 1
|
|
}
|
|
}
|
|
],
|
|
"SignerListID" : 0,
|
|
"SignerQuorum" : 3,
|
|
"index" : "92373B9F1683001079764527F0BD553ED8656A9934FE641A7F0A0BF4DB230E0E"
|
|
}
|
|
],
|
|
"ledger_current_index" : 16061438,
|
|
"status" : "success",
|
|
"validated" : false
|
|
}
|
|
}
|
|
</code></pre>
|
|
<h2 id="10-create-a-new-transaction-that-you-plan-to-multi-sign">10. Create a new transaction that you plan to multi-sign</h2>
|
|
<p>You have to specify <em>everything</em> about this transaction, including Fee and
|
|
Sequence. Also include the field <code>SigningPubKey</code> as an empty string -- this
|
|
indicates that the transaction is multi-signed.</p>
|
|
<p>Here's an example transaction we can send from our test account:</p>
|
|
<pre><code>{
|
|
"TransactionType": "TrustSet",
|
|
"Account": "rnBFvgZphmN39GWzUJeUitaP22Fr9be75H",
|
|
"Flags": 262144,
|
|
"LimitAmount": {
|
|
"currency": "USD",
|
|
"issuer": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
|
"value": "100"
|
|
},
|
|
"Sequence": 2,
|
|
"SigningPubKey":"",
|
|
"Fee": "12000"
|
|
}
|
|
</code></pre>
|
|
<p>(If you started from a fresh ledger, you first need to fund the account
|
|
specified by the <code>issuer</code> in this example, and then manually close the ledger.)</p>
|
|
<p>Keep in mind that the <code>Fee</code> for multi-signed transactions is significantly
|
|
higher than for regularly-signed transactions. It should be (N+1) times the
|
|
normal 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.</p>
|
|
<h2 id="11-get-a-signature-using-the-sign-for-command">11. Get a signature using the sign_for command</h2>
|
|
<pre><code>$ build/rippled sign_for rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW <rsA2's secret> '{
|
|
> "TransactionType": "TrustSet",
|
|
> "Account": "rnBFvgZphmN39GWzUJeUitaP22Fr9be75H",
|
|
> "Flags": 262144,
|
|
> "LimitAmount": {
|
|
> "currency": "USD",
|
|
> "issuer": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
|
> "value": "100"
|
|
> },
|
|
> "Sequence": 2,
|
|
> "SigningPubKey":"",
|
|
> "Fee": "12000"
|
|
> }'
|
|
Loading: "/home/mduo13/.config/ripple/rippled.cfg"
|
|
Connecting to 127.0.0.1:5005
|
|
{
|
|
"result" : {
|
|
"Signers" : [
|
|
{
|
|
"Signer" : {
|
|
"Account" : "rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW",
|
|
"SigningPubKey" : "02B3EC4E5DD96029A647CFA20DA07FE1F85296505552CCAC114087E66B46BD77DF",
|
|
"TxnSignature" : "304502210093EED0F75190385282C6369EE3C5C0FCC65227917F545EC8848B94E17105BC3D022073B3FB14452056FF8E966736150E2D75F3B7460AD7DEF6E2932ECD6690B6C3FE"
|
|
}
|
|
}
|
|
],
|
|
"status" : "success",
|
|
"tx_blob" : "1200142200040000240000000263D5038D7EA4C6800000000000000000000000000055534400000000004B4E9C06F24296074F7BC48F92A97916C6DC5EA9684000000000002EE0730081142DECAB42CA805119A9BA2FF305C9AFA12F0B86A1",
|
|
"tx_json" : {
|
|
"Account" : "rnBFvgZphmN39GWzUJeUitaP22Fr9be75H",
|
|
"Fee" : "12000",
|
|
"Flags" : 262144,
|
|
"LimitAmount" : {
|
|
"currency" : "USD",
|
|
"issuer" : "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
|
"value" : "100"
|
|
},
|
|
"Sequence" : 2,
|
|
"SigningPubKey" : "",
|
|
"TransactionType" : "TrustSet",
|
|
"hash" : "4622B2893AF3A70B4DB1FF86B25C10E92B71973895143E66029567A8541A8060"
|
|
}
|
|
}
|
|
}
|
|
</code></pre>
|
|
<p>The valuable part in the response is the <code>Signers</code> field. This is the part that
|
|
you're going to need later in order to construct the full, multi-signed
|
|
transaction.</p>
|
|
<p>The other parts, such as the <code>tx_blob</code>, are not very useful at this point,
|
|
unless you're "multi-signing" a transaction with only one signature.</p>
|
|
<h2 id="12-get-additional-signatures-the-same-way">12. Get additional signatures the same way</h2>
|
|
<p>If the accounts in your SignerList are funded accounts, the secret key you use
|
|
to sign for those accounts can come from the regular key (if they have one), or
|
|
the master key (unless it's disabled). For accounts that don't exist in the
|
|
ledger, you can only use the master secret associated with the address.</p>
|
|
<pre><code>$ build/rippled sign_for rUpy3eEg8rqjqfUoLeBnZkscbKbFsKXC3v <rUpy's secret> '{
|
|
"TransactionType": "TrustSet",
|
|
"Account": "rnBFvgZphmN39GWzUJeUitaP22Fr9be75H",
|
|
"Flags": 262144,
|
|
"LimitAmount": {
|
|
"currency": "USD",
|
|
"issuer": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
|
"value": "100"
|
|
},
|
|
"Sequence": 2,
|
|
"SigningPubKey":"",
|
|
"Fee": "12000"
|
|
}'
|
|
Loading: "/home/mduo13/.config/ripple/rippled.cfg"
|
|
Connecting to 127.0.0.1:5005
|
|
{
|
|
"result" : {
|
|
"Signers" : [
|
|
{
|
|
"Signer" : {
|
|
"Account" : "rUpy3eEg8rqjqfUoLeBnZkscbKbFsKXC3v",
|
|
"SigningPubKey" : "028FFB276505F9AC3F57E8D5242B386A597EF6C40A7999F37F1948636FD484E25B",
|
|
"TxnSignature" : "304402204C1A4FFE1628A4BBEA4E8BEDE7C7080B94299704207479D1334096721629DB9802206BB07EBAB23EA288D5714CF7D3231D041BBB2AFD973D24ED693197C4881DC2E1"
|
|
}
|
|
}
|
|
],
|
|
"status" : "success",
|
|
"tx_blob" : "1200142200040000240000000263D5038D7EA4C6800000000000000000000000000055534400000000004B4E9C06F24296074F7BC48F92A97916C6DC5EA9684000000000002EE0730081142DECAB42CA805119A9BA2FF305C9AFA12F0B86A1",
|
|
"tx_json" : {
|
|
"Account" : "rnBFvgZphmN39GWzUJeUitaP22Fr9be75H",
|
|
"Fee" : "12000",
|
|
"Flags" : 262144,
|
|
"LimitAmount" : {
|
|
"currency" : "USD",
|
|
"issuer" : "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
|
"value" : "100"
|
|
},
|
|
"Sequence" : 2,
|
|
"SigningPubKey" : "",
|
|
"TransactionType" : "TrustSet",
|
|
"hash" : "4622B2893AF3A70B4DB1FF86B25C10E92B71973895143E66029567A8541A8060"
|
|
}
|
|
}
|
|
}
|
|
</code></pre>
|
|
<p>Depending on the SignerList you configured, you may need to repeat this step
|
|
several times in order to get signatures from all the necessary parties.</p>
|
|
<h2 id="13-combine-the-signatures-and-submit">13. Combine the signatures and submit</h2>
|
|
<p>Take the contents of all the <code>Signers</code> arrays from all the responses, and
|
|
concatenate them in to a single <code>Signers</code> array field. The commandline syntax
|
|
for the <a href="rippled-apis.html#submit-multisigned"><code>submit_multisigned</code> command</a>
|
|
takes a single JSON object with two elements: this combined <code>Signers</code> array;
|
|
and <code>tx_json</code>, which is the transaction JSON that they signed.</p>
|
|
<p>This command actually submits the transaction for inclusion in the ledger. In
|
|
online mode, this relays it to other members of the network.</p>
|
|
<pre><code>$ build/rippled submit_multisigned ' {
|
|
> "Signers": [
|
|
> {
|
|
> "Signer" : {
|
|
> "Account" : "rUpy3eEg8rqjqfUoLeBnZkscbKbFsKXC3v",
|
|
> "SigningPubKey" : "028FFB276505F9AC3F57E8D5242B386A597EF6C40A7999F37F1948636FD484E25B",
|
|
> "TxnSignature" : "304402204C1A4FFE1628A4BBEA4E8BEDE7C7080B94299704207479D1334096721629DB9802206BB07EBAB23EA288D5714CF7D3231D041BBB2AFD973D24ED693197C4881DC2E1"
|
|
> }
|
|
> },
|
|
> {
|
|
> "Signer" : {
|
|
> "Account" : "rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW",
|
|
> "SigningPubKey" : "02B3EC4E5DD96029A647CFA20DA07FE1F85296505552CCAC114087E66B46BD77DF",
|
|
> "TxnSignature" : "304502210093EED0F75190385282C6369EE3C5C0FCC65227917F545EC8848B94E17105BC3D022073B3FB14452056FF8E966736150E2D75F3B7460AD7DEF6E2932ECD6690B6C3FE"
|
|
> }
|
|
> }
|
|
> ],
|
|
> "tx_json": {
|
|
> "TransactionType": "TrustSet",
|
|
> "Account": "rnBFvgZphmN39GWzUJeUitaP22Fr9be75H",
|
|
> "Flags": 262144,
|
|
> "LimitAmount": {
|
|
> "currency": "USD",
|
|
> "issuer": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
|
> "value": "100"
|
|
> },
|
|
> "Sequence": 2,
|
|
> "SigningPubKey":"",
|
|
> "Fee": "12000"
|
|
> }
|
|
> }'
|
|
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" : "1200142200040000240000000263D5038D7EA4C6800000000000000000000000000055534400000000004B4E9C06F24296074F7BC48F92A97916C6DC5EA9684000000000002EE0730081142DECAB42CA805119A9BA2FF305C9AFA12F0B86A1F3E010732102B3EC4E5DD96029A647CFA20DA07FE1F85296505552CCAC114087E66B46BD77DF7447304502210093EED0F75190385282C6369EE3C5C0FCC65227917F545EC8848B94E17105BC3D022073B3FB14452056FF8E966736150E2D75F3B7460AD7DEF6E2932ECD6690B6C3FE8114204288D2E47F8EF6C99BCC457966320D12409711E1E0107321028FFB276505F9AC3F57E8D5242B386A597EF6C40A7999F37F1948636FD484E25B7446304402204C1A4FFE1628A4BBEA4E8BEDE7C7080B94299704207479D1334096721629DB9802206BB07EBAB23EA288D5714CF7D3231D041BBB2AFD973D24ED693197C4881DC2E181147908A7F0EDD48EA896C3580A399F0EE78611C8E3E1F1",
|
|
"tx_json" : {
|
|
"Account" : "rnBFvgZphmN39GWzUJeUitaP22Fr9be75H",
|
|
"Fee" : "12000",
|
|
"Flags" : 262144,
|
|
"LimitAmount" : {
|
|
"currency" : "USD",
|
|
"issuer" : "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
|
"value" : "100"
|
|
},
|
|
"Sequence" : 2,
|
|
"Signers" : [
|
|
{
|
|
"Signer" : {
|
|
"Account" : "rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW",
|
|
"SigningPubKey" : "02B3EC4E5DD96029A647CFA20DA07FE1F85296505552CCAC114087E66B46BD77DF",
|
|
"TxnSignature" : "304502210093EED0F75190385282C6369EE3C5C0FCC65227917F545EC8848B94E17105BC3D022073B3FB14452056FF8E966736150E2D75F3B7460AD7DEF6E2932ECD6690B6C3FE"
|
|
}
|
|
},
|
|
{
|
|
"Signer" : {
|
|
"Account" : "rUpy3eEg8rqjqfUoLeBnZkscbKbFsKXC3v",
|
|
"SigningPubKey" : "028FFB276505F9AC3F57E8D5242B386A597EF6C40A7999F37F1948636FD484E25B",
|
|
"TxnSignature" : "304402204C1A4FFE1628A4BBEA4E8BEDE7C7080B94299704207479D1334096721629DB9802206BB07EBAB23EA288D5714CF7D3231D041BBB2AFD973D24ED693197C4881DC2E1"
|
|
}
|
|
}
|
|
],
|
|
"SigningPubKey" : "",
|
|
"TransactionType" : "TrustSet",
|
|
"hash" : "878C1C988305D87070F3E961FC27AC9D02C46FFDD92FC7EBB74E962344E58C78"
|
|
}
|
|
}
|
|
}
|
|
</code></pre>
|
|
<p>Take note of the <code>hash</code> value from the response (In this case, it's
|
|
<code>878C1C988305D87070F3E961FC27AC9D02C46FFDD92FC7EBB74E962344E58C78</code>) so you can
|
|
check the results of the transaction later.</p>
|
|
<h2 id="14-manually-close-the-ledger-one-last-time">14. Manually close the ledger one last time</h2>
|
|
<p>Once again, you would wait for the ledger to close on a live network. We use
|
|
the <a href="rippled-apis.html#ledger-accept"><code>ledger_accept</code> command</a> to manually
|
|
close the ledger when running <code>rippled</code> in stand-alone mode.</p>
|
|
<pre><code>$ build/rippled ledger_accept
|
|
Loading: "/home/mduo13/.config/ripple/rippled.cfg"
|
|
Connecting to 127.0.0.1:5005
|
|
{
|
|
"result" : {
|
|
"ledger_current_index" : 16061439,
|
|
"status" : "success"
|
|
}
|
|
}
|
|
</code></pre>
|
|
<h2 id="15-confirm-the-results-of-the-transaction">15. Confirm the results of the transaction</h2>
|
|
<p>Use the hash value from the response to the <code>submit_multisigned</code> command.</p>
|
|
<pre><code>$ build/rippled tx 878C1C988305D87070F3E961FC27AC9D02C46FFDD92FC7EBB74E962344E58C78
|
|
Loading: "/home/mduo13/.config/ripple/rippled.cfg"
|
|
Connecting to 127.0.0.1:5005
|
|
{
|
|
"result" : {
|
|
"Account" : "rnBFvgZphmN39GWzUJeUitaP22Fr9be75H",
|
|
"Fee" : "12000",
|
|
"Flags" : 262144,
|
|
"LimitAmount" : {
|
|
"currency" : "USD",
|
|
"issuer" : "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
|
"value" : "100"
|
|
},
|
|
"Sequence" : 2,
|
|
"Signers" : [
|
|
{
|
|
"Signer" : {
|
|
"Account" : "rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW",
|
|
"SigningPubKey" : "02B3EC4E5DD96029A647CFA20DA07FE1F85296505552CCAC114087E66B46BD77DF",
|
|
"TxnSignature" : "304502210093EED0F75190385282C6369EE3C5C0FCC65227917F545EC8848B94E17105BC3D022073B3FB14452056FF8E966736150E2D75F3B7460AD7DEF6E2932ECD6690B6C3FE"
|
|
}
|
|
},
|
|
{
|
|
"Signer" : {
|
|
"Account" : "rUpy3eEg8rqjqfUoLeBnZkscbKbFsKXC3v",
|
|
"SigningPubKey" : "028FFB276505F9AC3F57E8D5242B386A597EF6C40A7999F37F1948636FD484E25B",
|
|
"TxnSignature" : "304402204C1A4FFE1628A4BBEA4E8BEDE7C7080B94299704207479D1334096721629DB9802206BB07EBAB23EA288D5714CF7D3231D041BBB2AFD973D24ED693197C4881DC2E1"
|
|
}
|
|
}
|
|
],
|
|
"SigningPubKey" : "",
|
|
"TransactionType" : "TrustSet",
|
|
"date" : 496881900,
|
|
"hash" : "878C1C988305D87070F3E961FC27AC9D02C46FFDD92FC7EBB74E962344E58C78",
|
|
"inLedger" : 16061438,
|
|
"ledger_index" : 16061438,
|
|
"meta" : {
|
|
"AffectedNodes" : [
|
|
{
|
|
"ModifiedNode" : {
|
|
"LedgerEntryType" : "AccountRoot",
|
|
"LedgerIndex" : "13F1A95D7AAB7108D5CE7EEAF504B2894B8C674E6D68499076441C4837282BF8",
|
|
"PreviousTxnID" : "6ECC8C16B76D9B9AB099CA96DD653D8A321C34F1E5972D5EE6DBA19418F4D0CC",
|
|
"PreviousTxnLgrSeq" : 16061436
|
|
}
|
|
},
|
|
{
|
|
"ModifiedNode" : {
|
|
"FinalFields" : {
|
|
"Flags" : 0,
|
|
"Owner" : "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
|
"RootIndex" : "3B9C0CE77FCE7BCEE1A68F1E26AC467AF326239D0D816CE705E4A0E2DAD03F6D"
|
|
},
|
|
"LedgerEntryType" : "DirectoryNode",
|
|
"LedgerIndex" : "3B9C0CE77FCE7BCEE1A68F1E26AC467AF326239D0D816CE705E4A0E2DAD03F6D"
|
|
}
|
|
},
|
|
{
|
|
"CreatedNode" : {
|
|
"LedgerEntryType" : "RippleState",
|
|
"LedgerIndex" : "3C75A1F3DB61406AC2A9493038E8394A73F103C9229695AC7E57EB0F8AFC69E4",
|
|
"NewFields" : {
|
|
"Balance" : {
|
|
"currency" : "USD",
|
|
"issuer" : "rrrrrrrrrrrrrrrrrrrrBZbvji",
|
|
"value" : "0"
|
|
},
|
|
"Flags" : 65536,
|
|
"HighLimit" : {
|
|
"currency" : "USD",
|
|
"issuer" : "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
|
"value" : "0"
|
|
},
|
|
"LowLimit" : {
|
|
"currency" : "USD",
|
|
"issuer" : "rnBFvgZphmN39GWzUJeUitaP22Fr9be75H",
|
|
"value" : "100"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"ModifiedNode" : {
|
|
"FinalFields" : {
|
|
"Account" : "rnBFvgZphmN39GWzUJeUitaP22Fr9be75H",
|
|
"Balance" : "109978000",
|
|
"Flags" : 0,
|
|
"OwnerCount" : 6,
|
|
"Sequence" : 3
|
|
},
|
|
"LedgerEntryType" : "AccountRoot",
|
|
"LedgerIndex" : "3D728C1F82CFE419F2DC58707D1AD06E985A29217D21A991ADF154184B664F4F",
|
|
"PreviousFields" : {
|
|
"Balance" : "109990000",
|
|
"OwnerCount" : 5,
|
|
"Sequence" : 2
|
|
},
|
|
"PreviousTxnID" : "3950D98AD20DA52EBB1F3937EF32F382D74092A4C8DF9A0B1A06ED25200B5756",
|
|
"PreviousTxnLgrSeq" : 16061437
|
|
}
|
|
},
|
|
{
|
|
"ModifiedNode" : {
|
|
"FinalFields" : {
|
|
"Flags" : 0,
|
|
"Owner" : "rnBFvgZphmN39GWzUJeUitaP22Fr9be75H",
|
|
"RootIndex" : "95DA402B4D58FBFF6BAA4CB84BBC21348CC273949B61FEBCE758410EF90D147D"
|
|
},
|
|
"LedgerEntryType" : "DirectoryNode",
|
|
"LedgerIndex" : "95DA402B4D58FBFF6BAA4CB84BBC21348CC273949B61FEBCE758410EF90D147D"
|
|
}
|
|
}
|
|
],
|
|
"TransactionIndex" : 0,
|
|
"TransactionResult" : "tesSUCCESS"
|
|
},
|
|
"status" : "success",
|
|
"validated" : true
|
|
}
|
|
}
|
|
</code></pre>
|
|
<p>In particular, check that the <code>TransactionResult</code> is the string <code>tesSUCCESS</code>. </p>
|
|
<p>On the live network, you must also confirm that the <code>validated</code> field is set to
|
|
the boolean <code>true</code>. If not, 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 <code>validated</code> if it has been manually closed.</p>
|
|
</div>
|
|
</main>
|
|
</div>
|
|
<footer class="content-info" role="contentinfo">
|
|
<div class="container">
|
|
<div class="row">
|
|
<section class="col-sm-3 widget nav_menu-3 widget_nav_menu">
|
|
<h4>Resources<hr/></h4>
|
|
<ul class="menu" id="menu-resources">
|
|
<li class="menu-insights"><a href="https://ripple.com/insights/">Insights</a></li>
|
|
<li class="menu-press-center"><a href="https://ripple.com/press-center/">Press Center</a></li>
|
|
<li class="menu-media-resources"><a href="https://ripple.com/media-resources/">Media Resources</a></li>
|
|
<li class="menu-videos"><a href="https://ripple.com/videos/">Videos</a></li>
|
|
<li class="menu-whitepapers-reports"><a href="https://ripple.com/whitepapers-reports/">Whitepapers & Reports</a></li>
|
|
<li class="menu-xrp-portal"><a href="https://ripple.com/xrp-portal/">XRP Portal</a></li>
|
|
</ul>
|
|
</section>
|
|
<section class="col-sm-3 widget nav_menu-5 widget_nav_menu">
|
|
<h4>Regulators<hr/></h4>
|
|
<ul class="menu" id="menu-compliance-regulatory-relations"><li class="menu-compliance"><a href="https://ripple.com/compliance/">Compliance</a></li>
|
|
<li class="menu-policy-framework"><a href="https://ripple.com/policy-framework/">Policy Framework</a></li>
|
|
</ul>
|
|
</section>
|
|
<section class="col-sm-3 widget nav_menu-4 widget_nav_menu">
|
|
<h4>Support<hr/></h4>
|
|
<ul class="menu" id="menu-dev-footer-menu">
|
|
<li class="menu-contact-us"><a href="https://ripple.com/contact/">Contact Us</a></li>
|
|
<li class="active menu-developer-center"><a href="https://ripple.com/build/">Developer Center</a></li>
|
|
<li class="menu-knowledge-center"><a href="https://ripple.com/learn/">Knowledge Center</a></li>
|
|
<li class="menu-ripple-forum"><a href="https://forum.ripple.com/" target="_blank">Ripple Forum</a></li>
|
|
</ul>
|
|
</section>
|
|
<section class="col-sm-3 widget nav_menu-2 widget_nav_menu">
|
|
<h4>About<hr/></h4>
|
|
<ul class="menu" id="menu-company-footer">
|
|
<li class="menu-our-company"><a href="https://ripple.com/company/">Our Company</a></li>
|
|
<li class="menu-careers"><a href="https://ripple.com/company/careers/">Careers</a></li>
|
|
</ul>
|
|
</section>
|
|
<div class="col-sm-12 absolute_bottom_footer">
|
|
<div class="col-sm-8">
|
|
<span>© 2013-2015 Ripple Labs, Inc. All Rights Reserved.</span>
|
|
<span><a href="https://ripple.com/terms-of-use/">Terms</a></span>
|
|
<span><a href="https://ripple.com/privacy-policy/">Privacy</a></span>
|
|
</div>
|
|
</div><!-- /.absolute_bottom_footer -->
|
|
</div><!-- /.row -->
|
|
</div><!-- /.container -->
|
|
</footer>
|
|
</body>
|
|
</html>
|