# Set Up Multi-Signing [Multi-signing](/es-es/docs/concepts/accounts/multi-signing) is one of three ways to authorize [transactions](/es-es/docs/concepts/transactions) for the XRP Ledger, alongside signing with [regular keys and master keys](/es-es/docs/concepts/accounts/cryptographic-keys). You can configure your [address](/es-es/docs/concepts/accounts) to allow any combination of the three methods to authorize transactions. This tutorial demonstrates how to enable multi-signing for an address. ## Prerequisites - You must have a funded XRP Ledger [address](/es-es/docs/concepts/accounts) with enough spare XRP to send transactions and meet the [reserve requirement](/es-es/docs/concepts/accounts/reserves) of a new signer list. - With the [MultiSignReserve amendment](/resources/known-amendments#multisignreserve) enabled, multi-signing requires 0.2 XRP 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**.) - If you are on a test network that does not have the [MultiSignReserve amendment](/resources/known-amendments#multisignreserve) enabled, multi-signing requires more than the usual amount of XRP for the [account reserve](/es-es/docs/concepts/accounts/reserves), increasing with the number of signers in the list. - 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](/docs/references/http-websocket-apis/admin-api-methods/key-generation-methods/wallet_propose) is admin-only. - 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. - 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](/docs/references/http-websocket-apis/admin-api-methods/key-generation-methods/wallet_propose). 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](/es-es/docs/concepts/transactions#signing-and-submitting-transactions) a [SignerListSet transaction](/docs/references/protocol/transactions/types/signerlistset) 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. Caution Never submit a secret key to a server you do not control. Do not send a secret key unencrypted over the network. Commandline ``` $ 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" } } } ``` Javascript const { wallet: wallet1 } = await client.fundWallet() const { wallet: wallet2 } = await client.fundWallet() const { wallet: walletMaster } = await client.fundWallet() const signerListSet: SignerListSet = { TransactionType: 'SignerListSet', Account: walletMaster.classicAddress, SignerEntries: [ { SignerEntry: { Account: wallet1.classicAddress, SignerWeight: 1, }, }, { SignerEntry: { Account: wallet2.classicAddress, SignerWeight: 1, }, }, ], SignerQuorum: 2, } const signerListResponse = await client.submit(signerListSet, { wallet: walletMaster, }) console.log('SignerListSet constructed successfully:') console.log(signerListResponse) Python master_wallet = generate_faucet_wallet(client, debug=True) signer_wallet_1 = generate_faucet_wallet(client, debug=True) signer_wallet_2 = generate_faucet_wallet(client, debug=True) signer_entries = [ SignerEntry(account=signer_wallet_1.address, signer_weight=1), SignerEntry(account=signer_wallet_2.address, signer_weight=1), ] signer_list_set_tx = SignerListSet( account=master_wallet.address, signer_quorum=2, signer_entries=signer_entries, ) signed_signer_list_set_tx = autofill_and_sign(signer_list_set_tx, client, master_wallet) print("Constructed SignerListSet and submitting it to the ledger...") signed_list_set_tx_response = submit_and_wait( signed_signer_list_set_tx, client ) print("SignerListSet submitted, here's the response:") print(signed_list_set_tx_response) Make sure that the [Transaction Result](/es-es/docs/references/protocol/transactions/transaction-results) is [**`tesSUCCESS`**](/es-es/docs/references/protocol/transactions/transaction-results/tes-success). Otherwise, the transaction failed. If you have a problem in stand-alone mode or a non-production network, check that [multi-sign is enabled](/es-es/docs/infrastructure/testing-and-auditing/start-a-new-genesis-ledger-in-stand-alone-mode#settings-in-new-genesis-ledgers). Without the [MultiSignReserve amendment](/resources/known-amendments#multisignreserve), the more members in the signer list, the more XRP your address must have for purposes of the [owner reserve](/es-es/docs/concepts/accounts/reserves#owner-reserves). If your address does not have enough XRP, the transaction fails with [`tecINSUFFICIENT_RESERVE`](/es-es/docs/references/protocol/transactions/transaction-results/tec-codes). With the [MultiSignReserve amendment](/resources/known-amendments#multisignreserve) enabled, the XRP your address must have for purposes of the [owner reserve](/es-es/docs/concepts/accounts/reserves#owner-reserves) is 5 XRP, regardless of the number of members in the signer list. See also: [Signer Lists and Reserves](/es-es/docs/references/protocol/ledger-data/ledger-entry-types/signerlist#signer-lists-and-reserves). ## 4. Wait for validation On a live network (including Mainnet, Testnet, or Devnet), you can wait 4-7 seconds for the ledger to close automatically. If you're running `rippled` in stand-alone mode, use the [ledger_accept method](/docs/references/http-websocket-apis/admin-api-methods/server-control-methods/ledger_accept) to manually close the ledger. ## 5. Confirm the new signer list Use the [account_objects method](/docs/references/http-websocket-apis/public-api-methods/account-methods/account_objects) to confirm that the signer list is associated with the address in the latest validated ledger. Normally, an account can own many objects of different types (such as trust lines and offers). If you funded a new address for this tutorial, the signer list is the only object in the response. ``` $ 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 } } ``` If the signer list is present with the expected contents, then your address is ready to multi-sign. ## 6. Further steps At this point, your address is ready to [send a multi-signed transaction](/es-es/docs/tutorials/how-tos/manage-account-settings/send-a-multi-signed-transaction). You may also want to: * [Disable the address's master key pair](/es-es/docs/tutorials/how-tos/manage-account-settings/disable-master-key-pair). * [Remove the address's regular key pair](/es-es/docs/tutorials/how-tos/manage-account-settings/change-or-remove-a-regular-key-pair) (if you previously set one) by sending a [SetRegularKey transaction](/docs/references/protocol/transactions/types/setregularkey). ## See Also - **Concepts:** - [Cryptographic Keys](/es-es/docs/concepts/accounts/cryptographic-keys) - [Multi-Signing](/es-es/docs/concepts/accounts/multi-signing) - **Tutorials:** - [Install rippled](/es-es/docs/infrastructure/installation) - [Assign a Regular Key Pair](/es-es/docs/tutorials/how-tos/manage-account-settings/assign-a-regular-key-pair) - [Reliable Transaction Submission](/es-es/docs/concepts/transactions/reliable-transaction-submission) - [Enable Public Signing](/es-es/docs/infrastructure/configuration/enable-public-signing) - **References:** - [wallet_propose method](/docs/references/http-websocket-apis/admin-api-methods/key-generation-methods/wallet_propose) - [account_objects method](/docs/references/http-websocket-apis/public-api-methods/account-methods/account_objects) - [sign_for method](/docs/references/http-websocket-apis/admin-api-methods/signing-methods/sign_for) - [submit_multisigned method](/docs/references/http-websocket-apis/public-api-methods/transaction-methods/submit_multisigned) - [SignerListSet transaction](/docs/references/protocol/transactions/types/signerlistset) - [SignerList object](/es-es/docs/references/protocol/ledger-data/ledger-entry-types/signerlist)