mirror of
https://github.com/XRPLF/xrpl-dev-portal.git
synced 2026-02-04 22:15:19 +00:00
Compare commits
2 Commits
rewrite_di
...
rewrite_se
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6c9cee12da | ||
|
|
4eb7f0d8fc |
@@ -1,3 +0,0 @@
|
||||
# Disable Master Key Pair
|
||||
|
||||
Disable the master key pair that is connected to an account by default. WARNING: This can blackhole the account, making it so no one can use it or access its funds anymore.
|
||||
@@ -1,84 +0,0 @@
|
||||
import xrpl from 'xrpl'
|
||||
|
||||
const client = new xrpl.Client('wss://s.altnet.rippletest.net:51233')
|
||||
await client.connect()
|
||||
|
||||
console.log('Funding new wallet from faucet...')
|
||||
const { wallet } = await client.fundWallet()
|
||||
console.log(`Funded. Master key pair:
|
||||
Address: ${wallet.address}
|
||||
Seed: ${wallet.seed}
|
||||
`)
|
||||
|
||||
// Generate a regular key and assign it to the account -------------------------
|
||||
// Skip this step if you are using a pre-existing account that already has a
|
||||
// regular key or multi-signing list configured.
|
||||
// To black-hole an account, set the RegularKey to a well-known blackhole
|
||||
// address such as rrrrrrrrrrrrrrrrrrrrrhoLvTp instead.
|
||||
const algorithm = 'ed25519'
|
||||
const regularKeyPair = xrpl.Wallet.generate(algorithm)
|
||||
console.log(`Generated regular key pair:
|
||||
Address: ${regularKeyPair.address}
|
||||
Seed: ${regularKeyPair.seed}
|
||||
Algorithm: ${algorithm}
|
||||
`)
|
||||
const regularKeyTx = {
|
||||
TransactionType: 'SetRegularKey',
|
||||
Account: wallet.address,
|
||||
RegularKey: regularKeyPair.address
|
||||
}
|
||||
xrpl.validate(regularKeyTx)
|
||||
|
||||
console.log('Assigning regular key to the account...')
|
||||
const response = await client.submitAndWait(regularKeyTx, { wallet, autofill: true })
|
||||
const setRegularKeyResultCode = response.result.meta.TransactionResult
|
||||
if (setRegularKeyResultCode === 'tesSUCCESS') {
|
||||
console.log('Regular Key set successfully.')
|
||||
} else {
|
||||
console.error(`SetRegularKey failed with code ${setRegularKeyResultCode}.`)
|
||||
client.disconnect()
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
// Disable master key pair -----------------------------------------------------
|
||||
const disableMasterKeyTx = {
|
||||
TransactionType: 'AccountSet',
|
||||
Account: wallet.address,
|
||||
SetFlag: xrpl.AccountSetAsfFlags.asfDisableMaster
|
||||
}
|
||||
xrpl.validate(disableMasterKeyTx)
|
||||
|
||||
console.log('Disabling master key pair...')
|
||||
const response2 = await client.submitAndWait(disableMasterKeyTx, {
|
||||
wallet, // only the master key pair can disable itself
|
||||
autofill: true
|
||||
})
|
||||
const disableMasterResultCode = response2.result.meta.TransactionResult
|
||||
if (disableMasterResultCode === 'tesSUCCESS') {
|
||||
console.log('Master key disabled successfully.')
|
||||
} else {
|
||||
console.error(`AccountSet failed with code ${disableMasterResultCode}.`)
|
||||
client.disconnect()
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
// Confirm account flags -------------------------------------------------------
|
||||
const accountInfoResp = await client.request({
|
||||
command: 'account_info',
|
||||
account: wallet.address,
|
||||
ledger_index: 'validated'
|
||||
})
|
||||
if (accountInfoResp.error) {
|
||||
console.error('Error looking up account:', accountInfoResp.error)
|
||||
client.disconnect()
|
||||
process.exit(1)
|
||||
}
|
||||
console.log(`Flags for account ${wallet.address}:`)
|
||||
console.log(JSON.stringify(accountInfoResp.result.account_flags, null, 2))
|
||||
if (accountInfoResp.result.account_flags.disableMasterKey) {
|
||||
console.log('✅ Master key pair is disabled')
|
||||
} else {
|
||||
console.log('❌ Master key pair is ENABLED')
|
||||
}
|
||||
|
||||
client.disconnect()
|
||||
@@ -1,82 +0,0 @@
|
||||
import json
|
||||
from xrpl.clients import JsonRpcClient
|
||||
from xrpl.wallet import generate_faucet_wallet, Wallet
|
||||
from xrpl.models.transactions import SetRegularKey, AccountSet, AccountSetAsfFlag
|
||||
from xrpl.models.requests import AccountInfo
|
||||
from xrpl.transaction import submit_and_wait
|
||||
|
||||
client = JsonRpcClient("https://s.altnet.rippletest.net:51234")
|
||||
|
||||
print("Funding new wallet from faucet...")
|
||||
wallet = generate_faucet_wallet(client)
|
||||
print(f"""Funded. Master key pair:
|
||||
Address: {wallet.address}
|
||||
Seed: {wallet.seed}
|
||||
""")
|
||||
|
||||
# Generate a regular key and assign it to the account --------------------------
|
||||
# Skip this step if you are using a pre-existing account that already has a
|
||||
# regular key or multi-signing list configured.
|
||||
# To black-hole an account, set the RegularKey to a well-known blackhole
|
||||
# address such as rrrrrrrrrrrrrrrrrrrrrhoLvTp instead.
|
||||
algorithm = "ed25519"
|
||||
regular_key_pair = Wallet.create(algorithm)
|
||||
print(f"""Generated regular key pair:
|
||||
Address: {regular_key_pair.address}
|
||||
Seed: {regular_key_pair.seed}
|
||||
Algorithm: {algorithm}
|
||||
""")
|
||||
|
||||
regular_key_tx = SetRegularKey(
|
||||
account=wallet.address, regular_key=regular_key_pair.address
|
||||
)
|
||||
|
||||
print("Assigning regular key to the account...")
|
||||
try:
|
||||
response = submit_and_wait(regular_key_tx, client, wallet)
|
||||
except err:
|
||||
print("Submitting SetRegularKey transaction failed with error", err)
|
||||
exit(1)
|
||||
set_regular_key_result_code = response.result["meta"]["TransactionResult"]
|
||||
if set_regular_key_result_code == "tesSUCCESS":
|
||||
print("Regular Key set successfully.")
|
||||
else:
|
||||
print(f"SetRegularKey failed with code {set_regular_key_result_code}.")
|
||||
exit(1)
|
||||
|
||||
# Disable master key pair ------------------------------------------------------
|
||||
disable_master_key_tx = AccountSet(
|
||||
account=wallet.address, set_flag=AccountSetAsfFlag.ASF_DISABLE_MASTER
|
||||
)
|
||||
|
||||
print("Disabling master key pair...")
|
||||
response2 = submit_and_wait(
|
||||
disable_master_key_tx, client, wallet
|
||||
) # only the master key pair can disable itself
|
||||
disable_master_result_code = response2.result["meta"]["TransactionResult"]
|
||||
|
||||
if disable_master_result_code == "tesSUCCESS":
|
||||
print("Master key disabled successfully.")
|
||||
else:
|
||||
print(f"AccountSet failed with code {disable_master_result_code}.")
|
||||
exit(1)
|
||||
|
||||
# Confirm account flags --------------------------------------------------------
|
||||
account_info_request = AccountInfo(account=wallet.address, ledger_index="validated")
|
||||
try:
|
||||
account_info_resp = client.request(account_info_request)
|
||||
except Exception as e:
|
||||
print(f"Error requesting account_info: {e}")
|
||||
exit(1)
|
||||
if not account_info_resp.is_successful():
|
||||
print(f"Error looking up account: {account_info_resp.result}")
|
||||
exit(1)
|
||||
|
||||
account_flags = account_info_resp.result["account_flags"]
|
||||
print(f"Flags for account {wallet.address}:")
|
||||
print(json.dumps(account_flags, indent=2))
|
||||
|
||||
if account_flags["disableMasterKey"]:
|
||||
print("✅ Master key pair is disabled")
|
||||
else:
|
||||
print("❌ Master key pair is ENABLED")
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "disable-master-key",
|
||||
"version": "1.0.0",
|
||||
"name": "multisigning",
|
||||
"version": "3.0.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"xrpl": "^4.5.0"
|
||||
92
_code-samples/multisigning/js/set-up-multi-signing.js
Normal file
92
_code-samples/multisigning/js/set-up-multi-signing.js
Normal file
@@ -0,0 +1,92 @@
|
||||
import xrpl from 'xrpl'
|
||||
|
||||
const client = new xrpl.Client('wss://s.altnet.rippletest.net:51233')
|
||||
await client.connect()
|
||||
|
||||
console.log('Funding new wallet from faucet...')
|
||||
const { wallet } = await client.fundWallet()
|
||||
console.log(`Funded. Master key pair:
|
||||
Address: ${wallet.address}
|
||||
Seed: ${wallet.seed}
|
||||
`)
|
||||
|
||||
// Generate key pairs to use as signers ----------------------------------------
|
||||
// If each signer represents a separate person, they should generate their own
|
||||
// key pairs and send you just the address. These key pairs don't need to be
|
||||
// funded accounts in the ledger.
|
||||
const algorithm = 'ed25519'
|
||||
const signerAddresses = []
|
||||
for (let i = 0; i < 3; i++) {
|
||||
const signer = xrpl.Wallet.generate(algorithm)
|
||||
console.log(`Generated key pair for signer ${i + 1}:
|
||||
Address: ${signer.address}
|
||||
Seed: ${signer.seed}
|
||||
Algorithm: ${algorithm}
|
||||
`)
|
||||
signerAddresses.push(signer.address)
|
||||
}
|
||||
|
||||
// Send SignerListSet transaction ----------------------------------------------
|
||||
// This example sets up a 2-of-3 requirement with all signers weighted equally
|
||||
const signerEntries = []
|
||||
for (const signerAddress of signerAddresses) {
|
||||
signerEntries.push({
|
||||
SignerEntry: {
|
||||
Account: signerAddress,
|
||||
SignerWeight: 1
|
||||
}
|
||||
})
|
||||
}
|
||||
const signerListSetTx = {
|
||||
TransactionType: 'SignerListSet',
|
||||
Account: wallet.address,
|
||||
SignerQuorum: 2,
|
||||
SignerEntries: signerEntries
|
||||
}
|
||||
xrpl.validate(signerListSetTx)
|
||||
|
||||
console.log('Signing and submitting the SignerListSet transaction:',
|
||||
JSON.stringify(signerListSetTx, null, 2))
|
||||
const response = await client.submitAndWait(signerListSetTx, { wallet, autofill: true })
|
||||
|
||||
// Check result of the SignerListSet transaction -------------------------------
|
||||
console.log(JSON.stringify(response.result, null, 2))
|
||||
const listSetResultCode = response.result.meta.TransactionResult
|
||||
if (listSetResultCode === 'tesSUCCESS') {
|
||||
console.log('Signer list set successfully.')
|
||||
} else {
|
||||
console.error(`SignerListSet failed with code ${listSetResultCode}.`)
|
||||
client.disconnect()
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
// Confirm signer list ---------------------------------------------------------
|
||||
const accountInfoResp = await client.request({
|
||||
command: 'account_info',
|
||||
account: wallet.address,
|
||||
ledger_index: 'validated',
|
||||
signer_lists: true
|
||||
})
|
||||
if (accountInfoResp.error) {
|
||||
console.error('Error looking up account:', accountInfoResp.error)
|
||||
client.disconnect()
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
if (accountInfoResp.result.signer_lists) {
|
||||
const lists = accountInfoResp.result.signer_lists
|
||||
console.log(`Account has ${lists.length} signer list(s):`)
|
||||
for (const l of lists) {
|
||||
console.log(` List #${l.SignerListID} Quorum = ${l.SignerQuorum}`)
|
||||
for (const SEWrapper of l.SignerEntries) {
|
||||
const se = SEWrapper.SignerEntry
|
||||
console.log(` Signer ${se.Account} Weight = ${se.SignerWeight}`)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
console.error(`❌ No signer lists associated with ${wallet.address}`)
|
||||
client.disconnect()
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
client.disconnect()
|
||||
84
_code-samples/multisigning/py/set-up-multi-signing.py
Normal file
84
_code-samples/multisigning/py/set-up-multi-signing.py
Normal file
@@ -0,0 +1,84 @@
|
||||
import json
|
||||
from xrpl.clients import JsonRpcClient
|
||||
from xrpl.models.requests import AccountInfo
|
||||
from xrpl.models.transactions import SignerEntry, SignerListSet
|
||||
from xrpl.wallet import generate_faucet_wallet, Wallet
|
||||
from xrpl.transaction import submit_and_wait
|
||||
|
||||
client = JsonRpcClient("https://s.altnet.rippletest.net:51234")
|
||||
|
||||
print("Funding new wallet from faucet...")
|
||||
wallet = generate_faucet_wallet(client)
|
||||
print(f"""Funded. Master key pair:
|
||||
Address: {wallet.address}
|
||||
Seed: {wallet.seed}
|
||||
""")
|
||||
|
||||
# Generate key pairs to use as signers -----------------------------------------
|
||||
# If each signer represents a separate person, they should generate their own
|
||||
# key pairs and send you just the address. These key pairs don't need to be
|
||||
# funded accounts in the ledger.
|
||||
algorithm = "ed25519"
|
||||
signer_addresses = []
|
||||
for i in range(3):
|
||||
signer = Wallet.create(algorithm=algorithm)
|
||||
print(f"""Generated regular key pair:
|
||||
Address: {signer.address}
|
||||
Seed: {signer.seed}
|
||||
Algorithm: {algorithm}
|
||||
""")
|
||||
signer_addresses.append(signer.address)
|
||||
|
||||
# Send SignerListSet transaction -----------------------------------------------
|
||||
# This example sets up a 2-of-3 requirement with all signers weighted equally
|
||||
signer_list_set_tx = SignerListSet(
|
||||
account=wallet.address,
|
||||
signer_quorum=2,
|
||||
signer_entries=[
|
||||
SignerEntry(account=signer_address, signer_weight=1)
|
||||
for signer_address in signer_addresses
|
||||
],
|
||||
)
|
||||
|
||||
print(
|
||||
"Signing and submitting the SignerListSet transaction:",
|
||||
json.dumps(signer_list_set_tx.to_xrpl(), indent=2),
|
||||
)
|
||||
try:
|
||||
response = submit_and_wait(signer_list_set_tx, client, wallet)
|
||||
except err:
|
||||
print("Submitting SignerListSet transaction failed with error", err)
|
||||
exit(1)
|
||||
|
||||
# Check result of the SignerListSet transaction --------------------------------
|
||||
print(json.dumps(response.result, indent=2))
|
||||
signer_list_set_result_code = response.result["meta"]["TransactionResult"]
|
||||
if signer_list_set_result_code == "tesSUCCESS":
|
||||
print("Signer list set successfully.")
|
||||
else:
|
||||
print(f"SignerListSet failed with code {signer_list_set_result_code}.")
|
||||
exit(1)
|
||||
|
||||
# Confirm signer list ----------------------------------------------------------
|
||||
try:
|
||||
account_info_resp = client.request(
|
||||
AccountInfo(account=wallet.address, ledger_index="validated", signer_lists=True)
|
||||
)
|
||||
except err:
|
||||
print("Error requesting account_info:", err)
|
||||
exit(1)
|
||||
if not account_info_resp.is_successful():
|
||||
print("Error looking up account:", account_info_resp.result)
|
||||
exit(1)
|
||||
|
||||
if account_info_resp.result.get("signer_lists"):
|
||||
lists = account_info_resp.result["signer_lists"]
|
||||
print(f"Account has {len(lists)} signer list(s):")
|
||||
for l in lists:
|
||||
print(f" List #{l['SignerListID']} Quorum = {l['SignerQuorum']}")
|
||||
for se_wrapper in l["SignerEntries"]:
|
||||
se = se_wrapper["SignerEntry"]
|
||||
print(f" Signer {se['Account']} Weight = {se['SignerWeight']}")
|
||||
else:
|
||||
print(f"❌ No signer lists associated with {wallet.address}")
|
||||
exit(1)
|
||||
@@ -1,4 +1,6 @@
|
||||
---
|
||||
html: disable-master-key-pair.html
|
||||
parent: manage-account-settings.html
|
||||
seo:
|
||||
description: Disable the master key that is mathematically associated with an address.
|
||||
labels:
|
||||
@@ -7,140 +9,494 @@ labels:
|
||||
---
|
||||
# Disable Master Key Pair
|
||||
|
||||
This page describes how to disable the [master key pair](../../../concepts/accounts/cryptographic-keys.md) for an account. You should do this if your account's master key pair may have been compromised, or if you want to make [multi-signing](../../../concepts/accounts/multi-signing.md) the _only_ way to submit transactions from your account.
|
||||
This page describes how to disable the [master key pair](../../../concepts/accounts/cryptographic-keys.md) that is mathematically associated with an [account](../../../concepts/accounts/index.md)'s address. You should do this if your account's master key pair may have been compromised, or if you want to make [multi-signing](../../../concepts/accounts/multi-signing.md) the _only_ way to submit transactions from your account.
|
||||
|
||||
{% admonition type="danger" name="Warning" %}Disabling the master key pair removes the default method of [authorizing transactions](../../../concepts/transactions/index.md#authorizing-transactions). Before doing this, it's best to double-check that you can successfully send transactions using your regular key pair or multi-signing list. Due to the decentralized nature of the XRP Ledger, there is no one who can restore access to your account if something goes wrong.{% /admonition %}
|
||||
{% admonition type="danger" name="Warning" %}Disabling the master key pair removes one method of [authorizing transactions](../../../concepts/transactions/index.md#authorizing-transactions). You should be sure you can use one of the other ways of authorizing transactions, such as with a regular key or by multi-signing, before you disable the master key pair. (For example, if you [assigned a regular key pair](assign-a-regular-key-pair.md), make sure that you can successfully submit transactions with that regular key.) Due to the decentralized nature of the XRP Ledger, no one can restore access to your account if you cannot use the remaining ways of authorizing transactions.{% /admonition %}
|
||||
|
||||
## Goals
|
||||
|
||||
By following this tutorial, you should learn how to:
|
||||
|
||||
- Disable the master key pair for an account.
|
||||
- Check an account to see if its master key pair is disabled.
|
||||
**To disable the master key pair, you must use the master key pair.** However, you can _re-enable_ the master key pair using any other method of authorizing transactions.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
To complete this tutorial, you should:
|
||||
To disable the master key pair for an account, you must meet the following prerequisites:
|
||||
|
||||
- Have a basic understanding of the XRP Ledger.
|
||||
- Have an [XRP Ledger client library](../../../references/client-libraries.md), such as **xrpl.js**, installed.
|
||||
- Have a basic understanding of [Cryptographic Keys](../../../concepts/accounts/cryptographic-keys.md).
|
||||
- Know how to [assign a regular key pair](assign-a-regular-key-pair.md) or [set up multi-signing](set-up-multi-signing.md) for an account.
|
||||
|
||||
## Source Code
|
||||
|
||||
You can find the complete source code for this tutorial's examples in the {% repo-link path="_code-samples/disable-master-key/" %}code samples section of this website's repository{% /repo-link %}.
|
||||
- You must have an XRP Ledger [account](../../../concepts/accounts/index.md) and you must be able to sign and submit transactions from that account using the master key pair. See also: [Set Up Secure Signing](../../../concepts/transactions/secure-signing.md). Two common ways this can work are:
|
||||
- You know the account's master seed value. A seed value is commonly represented as a [base58][] value starting with "s", such as `sn3nxiW7v8KXzPzAqzyHXbSSKNuN9`.
|
||||
- Or, you use a [dedicated signing device](../../../concepts/transactions/secure-signing.md#use-a-dedicated-signing-device) that stores the seed value securely, so you don't need to know it.
|
||||
- Your account must have at least one method of authorizing transactions other than the master key pair. In other words, you must do one or both of the following:
|
||||
- [Assign a Regular Key Pair](assign-a-regular-key-pair.md).
|
||||
- [Set Up Multi-Signing](set-up-multi-signing.md).
|
||||
|
||||
## Steps
|
||||
|
||||
### 1. Install dependencies
|
||||
### 1. Construct Transaction JSON
|
||||
|
||||
Prepare an [AccountSet transaction][] from your account with the field `"SetValue": 4`. This is the value for the AccountSet flag "Disable Master" (`asfDisableMaster`). The only other required fields for this transaction are the required [common fields](../../../references/protocol/transactions/common-fields.md). For example, if you leave off the [auto-fillable fields](../../../references/protocol/transactions/common-fields.md#auto-fillable-fields), the following transaction instructions are enough:
|
||||
|
||||
```json
|
||||
{
|
||||
"TransactionType": "AccountSet",
|
||||
"Account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"SetFlag": 4
|
||||
}
|
||||
```
|
||||
|
||||
{% admonition type="success" name="Tip" %}It is strongly recommended to also provide the `LastLedgerSequence` field so that you can [reliably get the outcome of the transaction in a predictable amount of time](../../../concepts/transactions/reliable-transaction-submission.md).{% /admonition %}
|
||||
|
||||
### 2. Sign Transaction
|
||||
|
||||
You must use the **master key pair** to sign the transaction.
|
||||
|
||||
{% admonition type="danger" name="Warning" %}Do not submit your secret to a server you don't control, and do not send it over the network unencrypted. These examples assume you are using a [local `rippled` server](../../../concepts/transactions/secure-signing.md#run-rippled-locally). You should adapt these instructions if you are using another [secure signing configuration](../../../concepts/transactions/secure-signing.md).{% /admonition %}
|
||||
|
||||
#### Example Request
|
||||
|
||||
{% tabs %}
|
||||
{% tab label="JavaScript" %}
|
||||
From the code sample folder, use `npm` to install dependencies:
|
||||
|
||||
```sh
|
||||
npm i
|
||||
{% tab label="WebSocket" %}
|
||||
```json
|
||||
{
|
||||
"command": "sign",
|
||||
"tx_json": {
|
||||
"TransactionType": "AccountSet",
|
||||
"Account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"SetFlag": 4
|
||||
},
|
||||
"secret": "s████████████████████████████"
|
||||
}
|
||||
```
|
||||
{% /tab %}
|
||||
|
||||
{% tab label="Python" %}
|
||||
From the code sample folder, set up a virtual environment and use `pip` to install dependencies:
|
||||
|
||||
```sh
|
||||
python -m venv .venv
|
||||
source .venv/bin/activate
|
||||
pip install -r requirements.txt
|
||||
{% tab label="JSON-RPC" %}
|
||||
```json
|
||||
{
|
||||
"method": "sign",
|
||||
"params": [
|
||||
{
|
||||
"tx_json": {
|
||||
"TransactionType": "AccountSet",
|
||||
"Account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"SetFlag": 4
|
||||
},
|
||||
"secret": "s████████████████████████████"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
{% /tab %}
|
||||
|
||||
{% tab label="Commandline" %}
|
||||
```sh
|
||||
$ rippled sign s████████████████████████████ '{"TransactionType":"AccountSet",
|
||||
"Account":"rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", "SetFlag":4}'
|
||||
```
|
||||
{% /tab %}
|
||||
|
||||
{% /tabs %}
|
||||
|
||||
### 2. Connect and get account(s)
|
||||
|
||||
To get started, import the client library and instantiate an API client. For this tutorial, you need one account, which the sample code funds using the Testnet faucet; you could also use an existing account.
|
||||
#### Example Response
|
||||
|
||||
{% tabs %}
|
||||
{% tab label="JavaScript" %}
|
||||
{% code-snippet file="/_code-samples/disable-master-key/js/disable-master-key.js" language="js" before="// Generate a regular key" /%}
|
||||
|
||||
{% tab label="WebSocket" %}
|
||||
```json
|
||||
{
|
||||
"result": {
|
||||
"deprecated": "This command has been deprecated and will be removed in a future version of the server. Please migrate to a standalone signing tool.",
|
||||
"tx_blob": "1200032280000000240000017C20210000000468400000000000000A732103AB40A0490F9B7ED8DF29D246BF2D6269820A0EE7742ACDD457BEA7C7D0931EDB7446304402204457A890BC06F48061F8D61042975702B57EBEF3EA2C7C484DFE38CFD42EA11102202505A7C62FF41E68FDE10271BADD75BD66D54B2F96A326BE487A2728A352442D81144B4E9C06F24296074F7BC48F92A97916C6DC5EA9",
|
||||
"tx_json": {
|
||||
"Account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"Fee": "10",
|
||||
"Flags": 2147483648,
|
||||
"Sequence": 380,
|
||||
"SetFlag": 4,
|
||||
"SigningPubKey": "03AB40A0490F9B7ED8DF29D246BF2D6269820A0EE7742ACDD457BEA7C7D0931EDB",
|
||||
"TransactionType": "AccountSet",
|
||||
"TxnSignature": "304402204457A890BC06F48061F8D61042975702B57EBEF3EA2C7C484DFE38CFD42EA11102202505A7C62FF41E68FDE10271BADD75BD66D54B2F96A326BE487A2728A352442D",
|
||||
"hash": "327FD263132A4D08170E1B01FE1BB2E21D0126CE58165C97A9173CA9551BCD70"
|
||||
}
|
||||
},
|
||||
"status": "success",
|
||||
"type": "response"
|
||||
}
|
||||
```
|
||||
{% /tab %}
|
||||
|
||||
{% tab label="Python" %}
|
||||
{% code-snippet file="/_code-samples/disable-master-key/py/disable-master-key.py" language="py" before="# Generate a regular key" /%}
|
||||
{% tab label="JSON-RPC" %}
|
||||
```json
|
||||
{
|
||||
"result": {
|
||||
"deprecated": "This command has been deprecated and will be removed in a future version of the server. Please migrate to a standalone signing tool.",
|
||||
"status": "success",
|
||||
"tx_blob": "1200032280000000240000017C20210000000468400000000000000A732103AB40A0490F9B7ED8DF29D246BF2D6269820A0EE7742ACDD457BEA7C7D0931EDB7446304402204457A890BC06F48061F8D61042975702B57EBEF3EA2C7C484DFE38CFD42EA11102202505A7C62FF41E68FDE10271BADD75BD66D54B2F96A326BE487A2728A352442D81144B4E9C06F24296074F7BC48F92A97916C6DC5EA9",
|
||||
"tx_json": {
|
||||
"Account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"Fee": "10",
|
||||
"Flags": 2147483648,
|
||||
"Sequence": 380,
|
||||
"SetFlag": 4,
|
||||
"SigningPubKey": "03AB40A0490F9B7ED8DF29D246BF2D6269820A0EE7742ACDD457BEA7C7D0931EDB",
|
||||
"TransactionType": "AccountSet",
|
||||
"TxnSignature": "304402204457A890BC06F48061F8D61042975702B57EBEF3EA2C7C484DFE38CFD42EA11102202505A7C62FF41E68FDE10271BADD75BD66D54B2F96A326BE487A2728A352442D",
|
||||
"hash": "327FD263132A4D08170E1B01FE1BB2E21D0126CE58165C97A9173CA9551BCD70"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
{% /tab %}
|
||||
|
||||
{% tab label="Commandline" %}
|
||||
```sh
|
||||
Loading: "/etc/opt/ripple/rippled.cfg"
|
||||
2020-Feb-13 00:13:24.783570867 HTTPClient:NFO Connecting to 127.0.0.1:5005
|
||||
|
||||
{
|
||||
"result" : {
|
||||
"deprecated" : "This command has been deprecated and will be removed in a future version of the server. Please migrate to a standalone signing tool.",
|
||||
"status" : "success",
|
||||
"tx_blob" : "1200032280000000240000017C20210000000468400000000000000A732103AB40A0490F9B7ED8DF29D246BF2D6269820A0EE7742ACDD457BEA7C7D0931EDB7446304402204457A890BC06F48061F8D61042975702B57EBEF3EA2C7C484DFE38CFD42EA11102202505A7C62FF41E68FDE10271BADD75BD66D54B2F96A326BE487A2728A352442D81144B4E9C06F24296074F7BC48F92A97916C6DC5EA9",
|
||||
"tx_json" : {
|
||||
"Account" : "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"Fee" : "10",
|
||||
"Flags" : 2147483648,
|
||||
"Sequence" : 380,
|
||||
"SetFlag" : 4,
|
||||
"SigningPubKey" : "03AB40A0490F9B7ED8DF29D246BF2D6269820A0EE7742ACDD457BEA7C7D0931EDB",
|
||||
"TransactionType" : "AccountSet",
|
||||
"TxnSignature" : "304402204457A890BC06F48061F8D61042975702B57EBEF3EA2C7C484DFE38CFD42EA11102202505A7C62FF41E68FDE10271BADD75BD66D54B2F96A326BE487A2728A352442D",
|
||||
"hash" : "327FD263132A4D08170E1B01FE1BB2E21D0126CE58165C97A9173CA9551BCD70"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
{% /tab %}
|
||||
|
||||
{% /tabs %}
|
||||
|
||||
### 3. Set up another way of authorizing transactions
|
||||
Look for `"status": "success"` to indicate that the server successfully signed the transaction. If you get `"status": "error"` instead, check the `error` and `error_message` fields for more information. Some common possibilities include:
|
||||
|
||||
Before you can disable the master key pair, your account must have another way of authorizing transactions, either a regular key pair or a multi-signing list. Since the sample code uses a newly-funded account, it does not yet have either one, so it generates and assigns a regular key the same way as in the [Assign a Regular Key Pair tutorial](assign-a-regular-key-pair.md). **Skip this step if you are using an existing account that already has a regular key pair or multi-signing list set up.**
|
||||
- `"error": "badSecret"` usually means you made a typo in the `secret` of the request.
|
||||
- `"error": "masterDisabled"` means this address's master key pair is _already_ disabled.
|
||||
|
||||
Take note of the `tx_blob` value from the response. This is a signed transaction binary you can submit to the network.
|
||||
|
||||
### 3. Submit Transaction
|
||||
|
||||
Submit the signed transaction blob from the previous step to the XRP Ledger.
|
||||
|
||||
#### Example Request
|
||||
|
||||
{% tabs %}
|
||||
{% tab label="JavaScript" %}
|
||||
{% code-snippet file="/_code-samples/disable-master-key/js/disable-master-key.js" language="js" from="// Generate a regular key" before="// Disable master key" /%}
|
||||
|
||||
{% tab label="WebSocket" %}
|
||||
```json
|
||||
{
|
||||
"command": "submit",
|
||||
"tx_blob": "1200032280000000240000017C20210000000468400000000000000A732103AB40A0490F9B7ED8DF29D246BF2D6269820A0EE7742ACDD457BEA7C7D0931EDB7446304402204457A890BC06F48061F8D61042975702B57EBEF3EA2C7C484DFE38CFD42EA11102202505A7C62FF41E68FDE10271BADD75BD66D54B2F96A326BE487A2728A352442D81144B4E9C06F24296074F7BC48F92A97916C6DC5EA9"
|
||||
}
|
||||
```
|
||||
{% /tab %}
|
||||
|
||||
{% tab label="Python" %}
|
||||
{% code-snippet file="/_code-samples/disable-master-key/py/disable-master-key.py" language="py" from="# Generate a regular key" before="# Disable master key" /%}
|
||||
{% tab label="JSON-RPC" %}
|
||||
```json
|
||||
{
|
||||
"method":"submit",
|
||||
"params": [
|
||||
{
|
||||
"tx_blob": "1200032280000000240000017C20210000000468400000000000000A732103AB40A0490F9B7ED8DF29D246BF2D6269820A0EE7742ACDD457BEA7C7D0931EDB7446304402204457A890BC06F48061F8D61042975702B57EBEF3EA2C7C484DFE38CFD42EA11102202505A7C62FF41E68FDE10271BADD75BD66D54B2F96A326BE487A2728A352442D81144B4E9C06F24296074F7BC48F92A97916C6DC5EA9"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
{% /tab %}
|
||||
|
||||
{% tab label="Commandline" %}
|
||||
```
|
||||
$ rippled submit 1200032280000000240000017C20210000000468400000000000000A732103AB40A0490F9B7ED8DF29D246BF2D6269820A0EE7742ACDD457BEA7C7D0931EDB7446304402204457A890BC06F48061F8D61042975702B57EBEF3EA2C7C484DFE38CFD42EA11102202505A7C62FF41E68FDE10271BADD75BD66D54B2F96A326BE487A2728A352442D81144B4E9C06F24296074F7BC48F92A97916C6DC5EA9
|
||||
```
|
||||
{% /tab %}
|
||||
|
||||
{% /tabs %}
|
||||
|
||||
{% admonition type="success" name="Tip" %}If your goal is to make the account a [black hole](/docs/concepts/accounts/addresses#special-addresses) that cannot send transactions at all, you still need to set a regular key. Instead of generating a key pair, use a known black hole address such as **rrrrrrrrrrrrrrrrrrrrrhoLvTp**.{% /admonition %}
|
||||
|
||||
### 4. Disable the master key pair
|
||||
|
||||
To disable the master key pair, send an [AccountSet transaction][] with the `SetFlag` value set to the `asfDisableMaster` value (4). Unlike most transactions, this one MUST be signed with the **master key pair** for the account.
|
||||
#### Example Response
|
||||
|
||||
{% tabs %}
|
||||
{% tab label="JavaScript" %}
|
||||
{% code-snippet file="/_code-samples/disable-master-key/js/disable-master-key.js" language="js" from="// Disable master key" before="// Confirm account flags" /%}
|
||||
|
||||
{% tab label="WebSocket" %}
|
||||
```json
|
||||
{
|
||||
"result": {
|
||||
"engine_result" : "tesSUCCESS",
|
||||
"engine_result_code" : 0,
|
||||
"engine_result_message" : "The transaction was applied. Only final in a validated ledger.",
|
||||
"tx_blob" : "1200032280000000240000017C20210000000468400000000000000A732103AB40A0490F9B7ED8DF29D246BF2D6269820A0EE7742ACDD457BEA7C7D0931EDB7446304402204457A890BC06F48061F8D61042975702B57EBEF3EA2C7C484DFE38CFD42EA11102202505A7C62FF41E68FDE10271BADD75BD66D54B2F96A326BE487A2728A352442D81144B4E9C06F24296074F7BC48F92A97916C6DC5EA9",
|
||||
"tx_json" : {
|
||||
"Account" : "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"Fee" : "10",
|
||||
"Flags" : 2147483648,
|
||||
"Sequence" : 380,
|
||||
"SetFlag" : 4,
|
||||
"SigningPubKey" : "03AB40A0490F9B7ED8DF29D246BF2D6269820A0EE7742ACDD457BEA7C7D0931EDB",
|
||||
"TransactionType" : "AccountSet",
|
||||
"TxnSignature" : "304402204457A890BC06F48061F8D61042975702B57EBEF3EA2C7C484DFE38CFD42EA11102202505A7C62FF41E68FDE10271BADD75BD66D54B2F96A326BE487A2728A352442D",
|
||||
"hash" : "327FD263132A4D08170E1B01FE1BB2E21D0126CE58165C97A9173CA9551BCD70"
|
||||
}
|
||||
},
|
||||
"status": "success",
|
||||
"type": "response"
|
||||
}
|
||||
```
|
||||
{% /tab %}
|
||||
|
||||
{% tab label="Python" %}
|
||||
{% code-snippet file="/_code-samples/disable-master-key/py/disable-master-key.py" language="py" from="# Disable master key" before="# Confirm account flags" /%}
|
||||
{% tab label="JSON-RPC" %}
|
||||
```json
|
||||
{
|
||||
"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" : "1200032280000000240000017C20210000000468400000000000000A732103AB40A0490F9B7ED8DF29D246BF2D6269820A0EE7742ACDD457BEA7C7D0931EDB7446304402204457A890BC06F48061F8D61042975702B57EBEF3EA2C7C484DFE38CFD42EA11102202505A7C62FF41E68FDE10271BADD75BD66D54B2F96A326BE487A2728A352442D81144B4E9C06F24296074F7BC48F92A97916C6DC5EA9",
|
||||
"tx_json" : {
|
||||
"Account" : "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"Fee" : "10",
|
||||
"Flags" : 2147483648,
|
||||
"Sequence" : 380,
|
||||
"SetFlag" : 4,
|
||||
"SigningPubKey" : "03AB40A0490F9B7ED8DF29D246BF2D6269820A0EE7742ACDD457BEA7C7D0931EDB",
|
||||
"TransactionType" : "AccountSet",
|
||||
"TxnSignature" : "304402204457A890BC06F48061F8D61042975702B57EBEF3EA2C7C484DFE38CFD42EA11102202505A7C62FF41E68FDE10271BADD75BD66D54B2F96A326BE487A2728A352442D",
|
||||
"hash" : "327FD263132A4D08170E1B01FE1BB2E21D0126CE58165C97A9173CA9551BCD70"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
{% /tab %}
|
||||
|
||||
{% tab label="Commandline" %}
|
||||
```sh
|
||||
Loading: "/etc/opt/ripple/rippled.cfg"
|
||||
2020-Feb-13 00:25:49.361743460 HTTPClient:NFO 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" : "1200032280000000240000017C20210000000468400000000000000A732103AB40A0490F9B7ED8DF29D246BF2D6269820A0EE7742ACDD457BEA7C7D0931EDB7446304402204457A890BC06F48061F8D61042975702B57EBEF3EA2C7C484DFE38CFD42EA11102202505A7C62FF41E68FDE10271BADD75BD66D54B2F96A326BE487A2728A352442D81144B4E9C06F24296074F7BC48F92A97916C6DC5EA9",
|
||||
"tx_json" : {
|
||||
"Account" : "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"Fee" : "10",
|
||||
"Flags" : 2147483648,
|
||||
"Sequence" : 380,
|
||||
"SetFlag" : 4,
|
||||
"SigningPubKey" : "03AB40A0490F9B7ED8DF29D246BF2D6269820A0EE7742ACDD457BEA7C7D0931EDB",
|
||||
"TransactionType" : "AccountSet",
|
||||
"TxnSignature" : "304402204457A890BC06F48061F8D61042975702B57EBEF3EA2C7C484DFE38CFD42EA11102202505A7C62FF41E68FDE10271BADD75BD66D54B2F96A326BE487A2728A352442D",
|
||||
"hash" : "327FD263132A4D08170E1B01FE1BB2E21D0126CE58165C97A9173CA9551BCD70"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
{% /tab %}
|
||||
|
||||
{% /tabs %}
|
||||
|
||||
If the transaction fails with the result `tecNO_ALTERNATIVE_KEY`, your account does not have another method of authorizing transactions currently enabled. You must [assign a regular key pair](assign-a-regular-key-pair.md) or [set up multi-signing](set-up-multi-signing.md), then try again to disable the master key pair.
|
||||
|
||||
{% admonition type="success" name="Tip" %}
|
||||
If you later want to re-enable the master key pair, you can send an AccountSet transaction almost like this one, except for the following changes:
|
||||
- Use the `ClearFlag` field instead of the `SetFlag` field.
|
||||
- Sign the transaction using a regular key pair or multi-signing list. Naturally, you can't use the master key pair because it's disabled.
|
||||
{% /admonition %}
|
||||
|
||||
### 5. Confirm account flags
|
||||
### 4. Wait for validation
|
||||
|
||||
At this point the master key pair for the account should be disabled. You can confirm that this is the case using the [account_info method][] and checking the `disableMasterKey` field of `account_flags` in the result.
|
||||
{% raw-partial file="/docs/_snippets/wait-for-validation.md" /%}
|
||||
|
||||
### 5. Confirm Account Flags
|
||||
|
||||
Confirm that your account's master key is disabled using the [account_info method][]. Be sure to specify the following parameters:
|
||||
|
||||
| Field | Value |
|
||||
|:---------------|:------------------------------------------------------------|
|
||||
| `account` | The address of your account. |
|
||||
| `ledger_index` | `"validated"` to get results from the latest validated ledger version. |
|
||||
|
||||
#### Example Request
|
||||
|
||||
{% tabs %}
|
||||
|
||||
{% tab label="WebSocket" %}
|
||||
```json
|
||||
{
|
||||
"command": "account_info",
|
||||
"account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"ledger_index": "validated"
|
||||
}
|
||||
```
|
||||
{% /tab %}
|
||||
|
||||
{% tab label="JSON-RPC" %}
|
||||
```json
|
||||
{
|
||||
"method": "account_info",
|
||||
"params": [{
|
||||
"account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"ledger_index": "validated"
|
||||
}]
|
||||
}
|
||||
```
|
||||
{% /tab %}
|
||||
|
||||
{% tab label="Commandline" %}
|
||||
```sh
|
||||
rippled account_info rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn validated
|
||||
```
|
||||
{% /tab %}
|
||||
|
||||
{% /tabs %}
|
||||
|
||||
|
||||
#### Example Response
|
||||
|
||||
{% tabs %}
|
||||
|
||||
{% tab label="WebSocket" %}
|
||||
```json
|
||||
{
|
||||
"result": {
|
||||
"account_data": {
|
||||
"Account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"AccountTxnID": "327FD263132A4D08170E1B01FE1BB2E21D0126CE58165C97A9173CA9551BCD70",
|
||||
"Balance": "423013688",
|
||||
"Domain": "6D64756F31332E636F6D",
|
||||
"EmailHash": "98B4375E1D753E5B91627516F6D70977",
|
||||
"Flags": 9633792,
|
||||
"LedgerEntryType": "AccountRoot",
|
||||
"MessageKey": "0000000000000000000000070000000300",
|
||||
"OwnerCount": 9,
|
||||
"PreviousTxnID": "327FD263132A4D08170E1B01FE1BB2E21D0126CE58165C97A9173CA9551BCD70",
|
||||
"PreviousTxnLgrSeq": 53391321,
|
||||
"RegularKey": "rD9iJmieYHn8jTtPjwwkW2Wm9sVDvPXLoJ",
|
||||
"Sequence": 381,
|
||||
"TransferRate": 4294967295,
|
||||
"index": "13F1A95D7AAB7108D5CE7EEAF504B2894B8C674E6D68499076441C4837282BF8",
|
||||
"urlgravatar": "http://www.gravatar.com/avatar/98b4375e1d753e5b91627516f6d70977"
|
||||
},
|
||||
"ledger_hash": "A90CEBD4AEDA24470AAC5CD307B6D26267ACE79C03669A0A0B8C41ACAEDAA6F0",
|
||||
"ledger_index": 53391576,
|
||||
"validated": true
|
||||
},
|
||||
"status": "success",
|
||||
"type": "response"
|
||||
}
|
||||
```
|
||||
{% /tab %}
|
||||
|
||||
{% tab label="JSON-RPC" %}
|
||||
```json
|
||||
{
|
||||
"result": {
|
||||
"account_data": {
|
||||
"Account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"AccountTxnID": "327FD263132A4D08170E1B01FE1BB2E21D0126CE58165C97A9173CA9551BCD70",
|
||||
"Balance": "423013688",
|
||||
"Domain": "6D64756F31332E636F6D",
|
||||
"EmailHash": "98B4375E1D753E5B91627516F6D70977",
|
||||
"Flags": 9633792,
|
||||
"LedgerEntryType": "AccountRoot",
|
||||
"MessageKey": "0000000000000000000000070000000300",
|
||||
"OwnerCount": 9,
|
||||
"PreviousTxnID": "327FD263132A4D08170E1B01FE1BB2E21D0126CE58165C97A9173CA9551BCD70",
|
||||
"PreviousTxnLgrSeq": 53391321,
|
||||
"RegularKey": "rD9iJmieYHn8jTtPjwwkW2Wm9sVDvPXLoJ",
|
||||
"Sequence": 381,
|
||||
"TransferRate": 4294967295,
|
||||
"index": "13F1A95D7AAB7108D5CE7EEAF504B2894B8C674E6D68499076441C4837282BF8",
|
||||
"urlgravatar": "http://www.gravatar.com/avatar/98b4375e1d753e5b91627516f6d70977"
|
||||
},
|
||||
"ledger_hash": "4C4AC95149B13B539369998675FE6860C52695E83658366F18872181C9F1AEBF",
|
||||
"ledger_index": 53391589,
|
||||
"status": "success",
|
||||
"validated": true
|
||||
}
|
||||
}
|
||||
```
|
||||
{% /tab %}
|
||||
|
||||
{% tab label="Commandline" %}
|
||||
```sh
|
||||
Loading: "/etc/opt/ripple/rippled.cfg"
|
||||
2020-Feb-13 00:41:38.642710734 HTTPClient:NFO Connecting to 127.0.0.1:5005
|
||||
|
||||
{
|
||||
"result" : {
|
||||
"account_data" : {
|
||||
"Account" : "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"AccountTxnID" : "327FD263132A4D08170E1B01FE1BB2E21D0126CE58165C97A9173CA9551BCD70",
|
||||
"Balance" : "423013688",
|
||||
"Domain" : "6D64756F31332E636F6D",
|
||||
"EmailHash" : "98B4375E1D753E5B91627516F6D70977",
|
||||
"Flags" : 9633792,
|
||||
"LedgerEntryType" : "AccountRoot",
|
||||
"MessageKey" : "0000000000000000000000070000000300",
|
||||
"OwnerCount" : 9,
|
||||
"PreviousTxnID" : "327FD263132A4D08170E1B01FE1BB2E21D0126CE58165C97A9173CA9551BCD70",
|
||||
"PreviousTxnLgrSeq" : 53391321,
|
||||
"RegularKey" : "rD9iJmieYHn8jTtPjwwkW2Wm9sVDvPXLoJ",
|
||||
"Sequence" : 381,
|
||||
"TransferRate" : 4294967295,
|
||||
"index" : "13F1A95D7AAB7108D5CE7EEAF504B2894B8C674E6D68499076441C4837282BF8",
|
||||
"urlgravatar" : "http://www.gravatar.com/avatar/98b4375e1d753e5b91627516f6d70977"
|
||||
},
|
||||
"ledger_hash" : "BBA4034FB5D5D89987E0987A9491E7B62B16708EECFF04CDB0367BD4D28EB1B5",
|
||||
"ledger_index" : 53391568,
|
||||
"status" : "success",
|
||||
"validated" : true
|
||||
}
|
||||
}
|
||||
```
|
||||
{% /tab %}
|
||||
|
||||
{% /tabs %}
|
||||
|
||||
|
||||
In the response's `account_data` object, compare the `Flags` field with the `lsfDisableMaster` flag value (`0x00100000` in hex, or `1048576` in decimal) using bitwise-AND (the `&` operator in most common programming languages).
|
||||
|
||||
Example code:
|
||||
|
||||
{% tabs %}
|
||||
|
||||
{% tab label="JavaScript" %}
|
||||
{% code-snippet file="/_code-samples/disable-master-key/js/disable-master-key.js" language="js" from="// Confirm account flags" /%}
|
||||
```js
|
||||
// Assuming the JSON-RPC response above is saved as account_info_response
|
||||
const lsfDisableMaster = 0x00100000;
|
||||
let acct_flags = account_info_response.result.account_data.Flags;
|
||||
if ((lsfDisableMaster & acct_flags) === lsfDisableMaster) {
|
||||
console.log("Master key pair is DISABLED");
|
||||
} else {
|
||||
console.log("Master key pair is available for use");
|
||||
}
|
||||
```
|
||||
{% /tab %}
|
||||
|
||||
{% tab label="Python" %}
|
||||
{% code-snippet file="/_code-samples/disable-master-key/py/disable-master-key.py" language="py" from="# Confirm account flags" /%}
|
||||
```python
|
||||
# Assuming the JSON-RPC response above is parsed from JSON
|
||||
# and saved as the variable account_info_response
|
||||
lsfDisableMaster = 0x00100000
|
||||
acct_flags = account_info_response["result"]["account_data"]["Flags"]
|
||||
if lsfDisableMaster & acct_flags == lsfDisableMaster:
|
||||
print("Master key pair is DISABLED")
|
||||
else:
|
||||
print("Master key pair is available for use")
|
||||
```
|
||||
{% /tab %}
|
||||
|
||||
{% /tabs %}
|
||||
|
||||
If the result does not match your expectations, check whether the transaction you sent in the previous steps has executed successfully. It should be the most recent entry in the account's transaction history and it should have the result code `tesSUCCESS`. If you see any other [result code](../../../references/protocol/transactions/transaction-results/index.md), the transaction was not executed successfully.
|
||||
This operation has only two possible outcomes:
|
||||
|
||||
Another possibility that may occur is that the `account_info` response you received was slightly out of date, because it used the validated ledger from just _before_ your transaction was validated. This is especially likely when using public server clusters, where requests may go to different machines, but it can happen any time you request data from the ledger immediately after a transaction is validated. If you wait at least half a second and send the same `account_info` request again, you should get the updated results.
|
||||
- A nonzero result, equal to the `lsfDisableMaster` value, indicates **the master key has been successfully disabled**.
|
||||
- A zero result indicates the account's master key is not disabled.
|
||||
|
||||
You can look up the account on the [Testnet Explorer](https://testnet.xrpl.org/) to see if its master key pair is disabled in the most recent ledger version.
|
||||
|
||||
## See Also
|
||||
|
||||
For more information about this and related topics, see:
|
||||
|
||||
- **Concepts:**
|
||||
- [Cryptographic Keys](../../../concepts/accounts/cryptographic-keys.md)
|
||||
- [Multi-Signing](../../../concepts/accounts/multi-signing.md)
|
||||
- [Issuing and Operational Addresses](../../../concepts/accounts/account-types.md)
|
||||
- **Tutorials:**
|
||||
- [Assign a Regular Key Pair](assign-a-regular-key-pair.md)
|
||||
- [Change or Remove a Regular Key Pair](change-or-remove-a-regular-key-pair.md)
|
||||
- [Set Up Multi-Signing](set-up-multi-signing.md)
|
||||
- **References:**
|
||||
- [AccountSet transaction][]
|
||||
- [account_info method][]
|
||||
If the result does not match your expectations, check whether the transaction you sent in the previous steps has executed successfully. It should be the most recent entry in the account's transaction history ([account_tx method][]) and it should have the result code `tesSUCCESS`. If you see any other [result code](../../../references/protocol/transactions/transaction-results/index.md), the transaction was not executed successfully. Depending on the cause of the error, you may want to restart these steps from the beginning.
|
||||
|
||||
{% raw-partial file="/docs/_snippets/common-links.md" /%}
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
---
|
||||
html: set-up-multi-signing.html
|
||||
parent: manage-account-settings.html
|
||||
seo:
|
||||
description: Add a signer list to your account to enable multi-signing.
|
||||
labels:
|
||||
@@ -8,239 +6,141 @@ labels:
|
||||
---
|
||||
# Set Up Multi-Signing
|
||||
|
||||
[Multi-signing](../../../concepts/accounts/multi-signing.md) is one of three ways to authorize [transactions](../../../concepts/transactions/index.md) for the XRP Ledger, alongside signing with [regular keys and master keys](../../../concepts/accounts/cryptographic-keys.md). You can configure your [address](../../../concepts/accounts/index.md) to allow any combination of the three methods to authorize transactions.
|
||||
This tutorial shows up how to set up [multi-signing](../../../concepts/accounts/multi-signing.md) on your XRP Ledger account, which allows you to authorize transactions using signatures from a combination of keys. Various configurations are possible, but this tutorial shows a straightforward configuration requiring 2 of 3 signers to authorize a transaction.
|
||||
|
||||
This tutorial demonstrates how to enable multi-signing for an address.
|
||||
## Goals
|
||||
|
||||
By following this tutorial, you should learn how to:
|
||||
|
||||
- Generate key pairs you can use for multi-signing.
|
||||
- Add or update a signer list on your account.
|
||||
- Look up the signer list associated with an account, including its configured weights and quorum.
|
||||
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- You must have a funded XRP Ledger [address](../../../concepts/accounts/index.md) with enough spare XRP to send transactions and meet the [reserve requirement](../../../concepts/accounts/reserves.md) of a new signer list.
|
||||
To complete this tutorial, you should:
|
||||
|
||||
- With the [MultiSignReserve amendment][] enabled, multi-signing requires {% $env.PUBLIC_OWNER_RESERVE %} for the account reserve, regardless of the number of signers and signatures you use. (The MultiSignReserve amendment has been enabled in the production XRP Ledger since **2019-04-07**.)
|
||||
- Have a basic understanding of the XRP Ledger.
|
||||
- Have an [XRP Ledger client library](../../../references/client-libraries.md), such as **xrpl.js**, installed.
|
||||
- Have a basic understanding of [Cryptographic Keys](../../../concepts/accounts/cryptographic-keys.md) and [Multi-Signing](../../../concepts/accounts/multi-signing.md).
|
||||
|
||||
- If you are on a test network that does not have the [MultiSignReserve amendment][] enabled, multi-signing requires more than the usual amount of XRP for the [account reserve](../../../concepts/accounts/reserves.md), increasing with the number of signers in the list.
|
||||
## Source Code
|
||||
|
||||
- You must have access to a tool that can generate key pairs in the XRP Ledger format. If you are using a `rippled` server for this, you must have admin access because the [wallet_propose method][] is admin-only.
|
||||
You can find the complete source code for this tutorial's examples in the {% repo-link path="_code-samples/multisigning/" %}code samples section of this website's repository{% /repo-link %}.
|
||||
|
||||
- Alternatively, if you are authorizing others who already have XRP Ledger addresses to be signers for your address, you only need to know the account addresses of those people or entities.
|
||||
## Steps
|
||||
|
||||
- Multi-signing must be available. (The MultiSign amendment has been enabled in the production XRP Ledger since **2016-06-27**.)
|
||||
|
||||
## 1. Design Your Configuration
|
||||
|
||||
Decide how many signers you want to include (up to 32). Choose a quorum number for your signer list and weights for your signers based on how many signatures you want to require for a given transaction. For a straightforward "M-of-N" signing setup, assign each signer weight **`1`** and set your list's quorum to be "M", the number of signatures to require.
|
||||
|
||||
|
||||
## 2. Prepare member keys
|
||||
|
||||
You need one or more validly-formed XRP Ledger addresses to include as members of your signer list. You or your chosen signers must know the secret keys associated with these addresses. The addresses can be funded accounts that exist in the ledger, but they do not need to be.
|
||||
|
||||
You can generate new addresses using the [wallet_propose method][]. For example:
|
||||
|
||||
```
|
||||
$ rippled wallet_propose
|
||||
Loading: "/etc/opt/ripple/rippled.cfg"
|
||||
Connecting to 127.0.0.1:5005
|
||||
{
|
||||
"result" : {
|
||||
"account_id" : "rnRJ4dpSBKDR2M1itf4Ah6tZZm5xuNZFPH",
|
||||
"key_type" : "secp256k1",
|
||||
"master_key" : "FLOG SEND GOES CUFF GAGE FAT ANTI DEL GUM TIRE ISLE BEAR",
|
||||
"master_seed" : "snheH5UUjU4CWqiNVLny2k21TyKPC",
|
||||
"master_seed_hex" : "A9F859765EB8614D26809836382AFB82",
|
||||
"public_key" : "aBR4hxFXcDNHnGYvTiqb2KU8TTTV1cYV9wXTAuz2DjBm7S8TYEBU",
|
||||
"public_key_hex" : "03C09A5D112B393D531E4F092E3A5769A5752129F0A9C55C61B3A226BB9B567B9B",
|
||||
"status" : "success"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Take note of the `account_id` (XRP Ledger Address) and `master_seed` (secret key) for each one you generate.
|
||||
|
||||
|
||||
## 3. Send SignerListSet transaction
|
||||
|
||||
[Sign and submit](../../../concepts/transactions/index.md#signing-and-submitting-transactions) a [SignerListSet transaction][] in the normal (single-signature) way. This associates a signer list with your XRP Ledger address, so that a combination of signatures from the members of that signer list can multi-sign later transactions on your behalf.
|
||||
|
||||
In this example, the signer list 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.
|
||||
|
||||
{% partial file="/docs/_snippets/secret-key-warning.md" /%}
|
||||
### 1. Install dependencies
|
||||
|
||||
{% tabs %}
|
||||
{% tab label="JavaScript" %}
|
||||
From the code sample folder, use `npm` to install dependencies:
|
||||
|
||||
{% tab label="Commandline" %}
|
||||
```sh
|
||||
npm i
|
||||
```
|
||||
$ 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: "/etc/opt/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"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
{% /tab %}
|
||||
|
||||
{% tab label="Javascript" %}
|
||||
{% code-snippet file="/_code-samples/multisigning/js/multisigning.ts" language="js" from=" const { wallet: wallet1" before="const accountSet:" /%}
|
||||
{% /tab %}
|
||||
|
||||
{% tab label="Python" %}
|
||||
{% code-snippet file="/_code-samples/multisigning/py/multisigning.py" language="py" from="master_wallet =" before="# Now that" /%}
|
||||
{% /tab %}
|
||||
From the code sample folder, set up a virtual environment and use `pip` to install dependencies:
|
||||
|
||||
```sh
|
||||
python -m venv .venv
|
||||
source .venv/bin/activate
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
{% /tab %}
|
||||
{% /tabs %}
|
||||
|
||||
Make sure that the [Transaction Result](../../../references/protocol/transactions/transaction-results/index.md) is [**`tesSUCCESS`**](../../../references/protocol/transactions/transaction-results/tes-success.md). Otherwise, the transaction failed. If you have a problem in stand-alone mode or a non-production network, check that [multi-sign is enabled](../../../infrastructure/testing-and-auditing/start-a-new-genesis-ledger-in-stand-alone-mode.md#settings-in-new-genesis-ledgers).
|
||||
|
||||
{% admonition type="info" name="Note" %}Without the [MultiSignReserve amendment][], the more members in the signer list, the more XRP your address must have for purposes of the [owner reserve](../../../concepts/accounts/reserves.md#owner-reserves). If your address does not have enough XRP, the transaction fails with [`tecINSUFFICIENT_RESERVE`](../../../references/protocol/transactions/transaction-results/tec-codes.md). With the [MultiSignReserve amendment][] enabled, the XRP your address must have for purposes of the [owner reserve](../../../concepts/accounts/reserves.md#owner-reserves) is 5 XRP, regardless of the number of members in the signer list. See also: [Signer Lists and Reserves](../../../references/protocol/ledger-data/ledger-entry-types/signerlist.md#signer-lists-and-reserves).{% /admonition %}
|
||||
### 2. Connect and get account(s)
|
||||
|
||||
To get started, import the client library and instantiate an API client. For this tutorial, you need one account, which the sample code funds using the Testnet faucet; you could also use an existing account.
|
||||
|
||||
## 4. Wait for validation
|
||||
{% tabs %}
|
||||
{% tab label="JavaScript" %}
|
||||
{% code-snippet file="/_code-samples/multisigning/js/set-up-multi-signing.js" language="js" before="// Generate key pairs" /%}
|
||||
{% /tab %}
|
||||
|
||||
{% raw-partial file="/docs/_snippets/wait-for-validation.md" /%}
|
||||
{% tab label="Python" %}
|
||||
{% code-snippet file="/_code-samples/multisigning/py/set-up-multi-signing.py" language="py" before="# Generate key pairs" /%}
|
||||
{% /tab %}
|
||||
{% /tabs %}
|
||||
|
||||
### 3. Prepare signer keys
|
||||
|
||||
## 5. Confirm the new signer list
|
||||
Each signer on your list needs a key pair they can use to sign transactions. As the account owner, you only need to know the addresses, not the secret keys, of each signer. (One party knowing all the secret keys might defeat the purpose of multi-signing, depending on your use case.) These addresses _can_ have funded accounts in the ledger, but they don't have to.
|
||||
|
||||
Use the [account_objects method][] to confirm that the signer list is associated with the address in the latest validated ledger.
|
||||
Each signer should securely generate and store their own key pair, as you would any time you generate keys for an XRP Ledger account.
|
||||
|
||||
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 signer list is the only object in the response.
|
||||
{% tabs %}
|
||||
{% tab label="JavaScript" %}
|
||||
{% code-snippet file="/_code-samples/multisigning/js/set-up-multi-signing.js" language="js" from="// Generate key pairs" before="// Send SignerListSet transaction" /%}
|
||||
{% /tab %}
|
||||
|
||||
```
|
||||
$ rippled account_objects rEuLyBCvcw4CFmzv8RepSiAoNgF8tTGJQC validated
|
||||
Loading: "/etc/opt/ripple/rippled.cfg"
|
||||
Connecting to 127.0.0.1:5005
|
||||
{
|
||||
"result" : {
|
||||
"account" : "rEuLyBCvcw4CFmzv8RepSiAoNgF8tTGJQC",
|
||||
"account_objects" : [
|
||||
{
|
||||
"Flags" : 0,
|
||||
"LedgerEntryType" : "SignerList",
|
||||
"OwnerNode" : "0000000000000000",
|
||||
"PreviousTxnID" : "8FDC18960455C196A8C4DE0D24799209A21F4A17E32102B5162BD79466B90222",
|
||||
"PreviousTxnLgrSeq" : 5,
|
||||
"SignerEntries" : [
|
||||
{
|
||||
"SignerEntry" : {
|
||||
"Account" : "rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW",
|
||||
"SignerWeight" : 2
|
||||
}
|
||||
},
|
||||
{
|
||||
"SignerEntry" : {
|
||||
"Account" : "raKEEVSGnKSD9Zyvxu4z6Pqpm4ABH8FS6n",
|
||||
"SignerWeight" : 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"SignerEntry" : {
|
||||
"Account" : "rUpy3eEg8rqjqfUoLeBnZkscbKbFsKXC3v",
|
||||
"SignerWeight" : 1
|
||||
}
|
||||
}
|
||||
],
|
||||
"SignerListID" : 0,
|
||||
"SignerQuorum" : 3,
|
||||
"index" : "79FD203E4DDDF2EA78B798C963487120C048C78652A28682425E47C96D016F92"
|
||||
}
|
||||
],
|
||||
"ledger_hash" : "56E81069F06492FB410A70218C08169BE3AB3CFD5AEA20E999662D81DC361D9F",
|
||||
"ledger_index" : 5,
|
||||
"status" : "success",
|
||||
"validated" : true
|
||||
}
|
||||
}
|
||||
```
|
||||
{% tab label="Python" %}
|
||||
{% code-snippet file="/_code-samples/multisigning/py/set-up-multi-signing.py" language="py" from="# Generate key pairs" before="# Send SignerListSet transaction" /%}
|
||||
{% /tab %}
|
||||
{% /tabs %}
|
||||
|
||||
If the signer list is present with the expected contents, then your address is ready to multi-sign.
|
||||
For purposes of this tutorial, the sample code generates three key pairs and saves their addresses into an array.
|
||||
|
||||
## 6. Further steps
|
||||
### 4. Send SignerListSet transaction
|
||||
|
||||
At this point, your address is ready to [send a multi-signed transaction](send-a-multi-signed-transaction.md). You may also want to:
|
||||
Use a [SignerListSet transaction][] to assign a multi-signing list to your account. For this transaction, you set the total weight needed for a quorum in the `SignerQuorum` field, and the list of signers with their individual weights in the `SignerEntries` field. For 2-of-3 multi-signing, give each of the three signers a weight of `1` and set the quorum to `2`. Note that each object in the `SignerEntries` array must be a wrapper object with a single `SignerEntry` field.
|
||||
|
||||
* [Disable the address's master key pair](disable-master-key-pair.md).
|
||||
* [Remove the address's regular key pair](change-or-remove-a-regular-key-pair.md) (if you previously set one) by sending a [SetRegularKey transaction][].
|
||||
{% tabs %}
|
||||
{% tab label="JavaScript" %}
|
||||
{% code-snippet file="/_code-samples/multisigning/js/set-up-multi-signing.js" language="js" from="// Send SignerListSet transaction" before="// Confirm signer list" /%}
|
||||
{% /tab %}
|
||||
|
||||
{% tab label="Python" %}
|
||||
{% code-snippet file="/_code-samples/multisigning/py/set-up-multi-signing.py" language="py" from="# Send SignerListSet transaction" before="# Confirm signer list" /%}
|
||||
{% /tab %}
|
||||
{% /tabs %}
|
||||
|
||||
{% admonition type="success" name="Tip: Replacing Signer Lists" %}
|
||||
If you already have a multi-signing list configured for your account, you can use this same process to replace it with a new list. You can even use the old list to authorize the transaction.
|
||||
{% /admonition %}
|
||||
|
||||
### 5. Confirm that the signer list is assigned to your account
|
||||
|
||||
If the SignerListSet transaction succeeded, the list should now be associated with your account. For further confirmation, you can look up the list using the [account_info method][].
|
||||
|
||||
{% tabs %}
|
||||
{% tab label="JavaScript" %}
|
||||
{% code-snippet file="/_code-samples/multisigning/js/set-up-multi-signing.js" language="js" from="// Confirm signer list" /%}
|
||||
{% /tab %}
|
||||
|
||||
{% tab label="Python" %}
|
||||
{% code-snippet file="/_code-samples/multisigning/py/set-up-multi-signing.py" language="py" from="# Confirm signer list" /%}
|
||||
{% /tab %}
|
||||
{% /tabs %}
|
||||
|
||||
{% admonition type="info" name="Note" %}
|
||||
There currently is no way to have more than one multi-signing list assigned to your account, but the protocol is built to be expandable; every signer list has an ID number of `0`, so that a future [amendment](../../../concepts/networks-and-servers/amendments.md) could allow lists with other IDs. This is why the `signer_lists` field is an array in the `account_info` response.
|
||||
{% /admonition %}
|
||||
|
||||
## Next Steps
|
||||
|
||||
At this point, you can [send a multi-signed transaction](send-a-multi-signed-transaction.md). You may also want to:
|
||||
|
||||
* [Disable the master key pair](disable-master-key-pair.md).
|
||||
* [Remove the regular key pair](change-or-remove-a-regular-key-pair.md) (if you previously set one)
|
||||
|
||||
## See Also
|
||||
|
||||
- **Concepts:**
|
||||
- [Cryptographic Keys](../../../concepts/accounts/cryptographic-keys.md)
|
||||
- [Multi-Signing](../../../concepts/accounts/multi-signing.md)
|
||||
- [Cryptographic Keys](../../../concepts/accounts/cryptographic-keys.md)
|
||||
- [Multi-Signing](../../../concepts/accounts/multi-signing.md)
|
||||
- **Tutorials:**
|
||||
- [Install rippled](../../../infrastructure/installation/index.md)
|
||||
- [Assign a Regular Key Pair](assign-a-regular-key-pair.md)
|
||||
- [Reliable Transaction Submission](../../../concepts/transactions/reliable-transaction-submission.md)
|
||||
- [Enable Public Signing](../../../infrastructure/configuration/enable-public-signing.md)
|
||||
- [Send a Multi-signed Transaction](send-a-multi-signed-transaction.md)
|
||||
- [Assign a Regular Key Pair](assign-a-regular-key-pair.md)
|
||||
- [Reliable Transaction Submission](../../../concepts/transactions/reliable-transaction-submission.md)
|
||||
- **References:**
|
||||
- [wallet_propose method][]
|
||||
- [account_objects method][]
|
||||
- [sign_for method][]
|
||||
- [submit_multisigned method][]
|
||||
- [SignerListSet transaction][]
|
||||
- [SignerList object](../../../references/protocol/ledger-data/ledger-entry-types/signerlist.md)
|
||||
- [account_info method][]
|
||||
- [SignerListSet transaction][]
|
||||
- [SignerList entry][]
|
||||
|
||||
{% raw-partial file="/docs/_snippets/common-links.md" /%}
|
||||
|
||||
Reference in New Issue
Block a user